10

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

erik258
  • 14,701
  • 2
  • 25
  • 31
nikoss
  • 3,254
  • 2
  • 26
  • 40
  • Possible duplicate of [Getting error: unknown field in struct literal](https://stackoverflow.com/questions/33098460/getting-error-unknown-field-in-struct-literal) – Inanc Gumus Jun 25 '17 at 12:07

2 Answers2

16

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,
}
erik258
  • 14,701
  • 2
  • 25
  • 31
Andy Schweig
  • 6,597
  • 2
  • 16
  • 22
  • this is not the case this vill make one exta level of indention i need to embed account directly under returnAccount – nikoss Jan 17 '17 at 00:00
  • 2
    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. – Andy Schweig Jan 17 '17 at 00:01
  • 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 Jan 17 '17 at 00:07
  • can you make a minor change to your post so i can upvote actually i solved the issue your way – nikoss Jan 17 '17 at 00:26
  • There you go @nikoss, it finally happened – erik258 Nov 15 '19 at 22:06
10

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
Community
  • 1
  • 1
hassansin
  • 16,918
  • 3
  • 43
  • 49
  • 1
    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 – nikoss Jan 16 '17 at 23:52
  • 1
    Also see my answer for a way to do it without having to use separate assignments. – Andy Schweig Jan 16 '17 at 23:55