在Go语言中嵌入结构体会出现”unknown field”错误。

huangapple go评论76阅读模式
英文:

Embedding structs in golang gives error "unknown field"

问题

我在user包中有一个名为accountstruct

type Account struct {
    Tp              string                 `json:"type" bson:"type"`
    AccountId       string                 `json:"account_id" bson:"account_id"`
    Credentials     map[string]interface{} `json:"credentials,omitempty" bson:"credentials,omitempty"`
    ProfilePicture  string                 `json:"profile_picture,omitempty"`
    Username        string                 `json:"username" bson:"username"`
    AccessToken     map[string]interface{} `bson:"access_token,omitempty"`
}

user/accounts中,我试图将这个account结构嵌入到另一个结构中。

type returnAccount struct {
    user.Account
    AccessToken string `json:"access_token,omitempty"`
}

在成功导入user包之后,我尝试嵌入它,之前一直都能用。

最后,在一个循环中,我获取用户账户并将其映射为returnAccount,然后从函数中返回。以下是我的函数:

func getAccounts(usr *user.AuthenticatedUser, id ...string) (accounts map[string]returnAccount) {
    accounts = make(map[string]returnAccount)
    if len(id) > 0 {
        for _, v := range id {
            for _, acnt := range usr.Accounts {
                if acnt.AccountId == v {
                    accounts[acnt.AccountId] = returnAccount{
                        Tp:         acnt.Tp,
                        AccountId:  acnt.AccountId,
                    }
                }
            }
        }
        return
    }
    for _, v := range usr.Accounts {
        accounts[v.AccountId] = returnAccount{
            Tp:         v.Tp,
            AccountId:  v.AccountId,
            Username:   v.Username,
        }
    }
    return
}

然而,这段代码无法编译,以下是错误信息:

# sgin/api/user/accounts
api/user/accounts/getaccounts.go:16: unknown returnAccount field 'Tp' in struct literal
api/user/accounts/getaccounts.go:17: unknown returnAccount field 'AccountId' in struct literal
api/user/accounts/getaccounts.go:26: unknown returnAccount field 'Tp' in struct literal
api/user/accounts/getaccounts.go:27: unknown returnAccount field 'AccountId' in struct literal
api/user/accounts/getaccounts.go:28: unknown returnAccount field 'Username' in struct literal

一切看起来都很简单明了,我无法弄清楚为什么会出现这个错误,我需要访问Account结构的所有成员都是公开的。

我需要这个字段的原因是,我想通过API将访问令牌发送给客户端,但不包含密钥,同时我还想减少缩进级别。

英文:

i have a struct in user package called account

type Account struct {
	Tp          string `json:"type"bson:"type"`
	AccountId   string  `json:"account_id"bson:"account_id"`
	Credentials map[string]interface{} `json:"credentials,omitempty"bson:"credentials,omitempty"`
	ProfilePicture string `json:"profile_picture,omitempty"`
	Username string `json:"username"bson:"username"`
	AccessToken map[string]interface{}`bson:"access_token,omitempty"`
}

and in user/accounts im trying to embed this account struct into another struct

type returnAccount struct {
	user.Account
	AccessToken string `json:"access_token,omitempty"`
}

user package is properly imported before trying to embed i was using it successfully

finaly in a loop i am getting user accounts and making a map of returnAccount and returning from my function
here is my function

func getAccounts(usr *user.AuthenticatedUser, id ...string) (accounts map[string]returnAccount) {
	accounts = make(map[string]returnAccount)
	if len(id) > 0 {
		for _, v := range id {
			for _, acnt := range usr.Accounts {
				if acnt.AccountId == v {
					accounts[acnt.AccountId] = returnAccount{
						Tp:       acnt.Tp,
						AccountId:acnt.AccountId,
					}
				}
			}
		}
		return
	}
	for _, v := range usr.Accounts {
		accounts[v.AccountId] = returnAccount{
			Tp:       v.Tp,
			AccountId:v.AccountId,
			Username: v.Username,

		}

	}
	return
}

However this code wont compile here is the error message

# sgin/api/user/accounts
api/user/accounts/getaccounts.go:16: unknown returnAccount field 'Tp' in struct literal
api/user/accounts/getaccounts.go:17: unknown returnAccount field 'AccountId' in struct literal
api/user/accounts/getaccounts.go:26: unknown returnAccount field 'Tp' in struct literal
api/user/accounts/getaccounts.go:27: unknown returnAccount field 'AccountId' in struct literal
api/user/accounts/getaccounts.go:28: unknown returnAccount field 'Username' in struct literal

everything seems pretty straightforward and simple i cannot figure out why i get this error all members i need to reach of the Account struct are exported

The reason why i need this field is i want to send access token to clients through api but not the secret and also i want to reduce the indention level

答案1

得分: 16

你不能直接初始化嵌入类型中的字段,但可以像这样操作:

accounts[v.AccountId] = returnAccount{
	Account: Account{
		Tp:        v.Tp,
		AccountId: v.AccountId,
		Username:  v.Username,
	},
}

或者,如果v的类型是Account,你可以直接使用:

accounts[v.AccountId] = returnAccount{
	Account: v,
}
英文:

You can't initialize the fields in the embedded type directly, but you can do it like this:

accounts[v.AccountId] = returnAccount{
	Account: Account{
		Tp:        v.Tp,
		AccountId: v.AccountId,
		Username:  v.Username,
	},
}

Or, if v is of type Account, you can just use

accounts[v.AccountId] = returnAccount{
	Account: v,
}

答案2

得分: 10

你正在尝试初始化被提升的字段,但通过复合字面量是不可能的。根据Go规范

> 在结构体x中,如果匿名字段的字段或方法f被称为被提升的字段,那么x.f是一个合法的选择器,表示该字段或方法f。
>
> 被提升的字段就像结构体的普通字段一样,只是不能在结构体的复合字面量中用作字段名。

但你可以使用点表示法访问它们:

ra := returnAccount{}
ra.Tp = acnt.Tp
英文:

You are trying to initialize promoted fields which is not possible by composite literals. From Go spec:

> A field or method f of an anonymous field in a struct x is called promoted if x.f is a legal selector that denotes that field or method f.
>
>Promoted fields act like ordinary fields of a struct except that they cannot be used as field names in composite literals of the
> struct.

But you can access them using dot notation:

ra:= returnAccount{}
ra.Tp = acnt.Tp

huangapple
  • 本文由 发表于 2017年1月17日 07:28:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/41686692.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定