在golang中嵌入结构体会出现“未知字段”错误

11

我在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里实现。

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

在尝试嵌入之前,请确保已正确导入用户包,我之前使用它很成功。

最后,在循环中获取用户帐户并创建一个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将访问令牌发送给客户端,但不包括密钥,并且我想减少缩进级别。


可能是重复的问题:获取错误:结构体字面量中的未知字段 - Inanc Gumus
2个回答

16

您无法直接初始化嵌入类型中的字段,但可以按照以下方式执行:

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

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

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

这不是这种情况,这会增加一个额外的缩进级别,我需要直接将账户嵌入到returnAccount下面。 - nikoss
2
缩进无关紧要。这只是展示了如何使用字面量设置这些字段,而不是使用单独的赋值语句。如果您不想这样做,您不必这样做,但它与您尝试做的事情完全相同。请撤销您的反对票,因为这个答案是正确的。 - Andy Schweig
除非您编辑问题,否则该网站不允许我取消投票,而且问题在于账户结构将随着程序需要更多细节而不断增长,我不想手动在2个或更多地方键入所有更改,这不是我编写程序的方式。 - nikoss
你能对你的帖子做一个小改动吗,这样我就可以点赞了。实际上,我用你的方法解决了这个问题。 - nikoss
这就是你想要的,@nikoss,它终于发生了。 - erik258

10

您正在尝试初始化被提升字段,这在复合字面值中是不可能的。根据Go规范:

在结构体x中,匿名字段f的字段或方法f如果x.f是一个合法的选择器,表示该字段或方法f则称为提升字段。

提升字段的行为类似于结构体的普通字段,但它们不能在struct的复合字面值中用作字段名。

但是您可以使用点符号访问它们:

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

1
这解决了问题,但我并不是很理解这个主题,你能否再添加一些细节?我查看了规范,但意思并不是很清楚。@hassansin - nikoss
1
另外,查看我的答案,可以找到一种不需要使用单独赋值的方法。 - Andy Schweig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接