Embedding structs in golang gives error "unknown field"

11,297

Solution 1

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

Solution 2

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,
}
Share:
11,297
nikoss
Author by

nikoss

Updated on June 24, 2022

Comments

  • nikoss
    nikoss about 2 years

    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

  • nikoss
    nikoss over 7 years
    this solves the issue though i couldnt quite understand the topic can you please ad some more detail i checked the spec but the meanin is not very clear @hassansin
  • Andy Schweig
    Andy Schweig over 7 years
    Also see my answer for a way to do it without having to use separate assignments.
  • nikoss
    nikoss over 7 years
    this is not the case this vill make one exta level of indention i need to embed account directly under returnAccount
  • Andy Schweig
    Andy Schweig over 7 years
    The indentation is irrelevant. This just shows how you can set those fields in a literal as opposed to doing it with separate assignments. You don't have to do it this way if you don't want to, but it's identical to what you were trying to do. Please remove your down vote as this answer is correct.
  • nikoss
    nikoss over 7 years
    unless you edit the question the site does not allow me to remove the vote and the point is that the account struct will keep growing as the program needs more details i dont want to type all changes to 2 or more places by hand its not the way i prefer to write programs
  • nikoss
    nikoss over 7 years
    can you make a minor change to your post so i can upvote actually i solved the issue your way
  • erik258
    erik258 over 4 years
    There you go @nikoss, it finally happened