How to initialise nested structs in go? [duplicate]

早过忘川 提交于 2019-12-19 11:47:18

问题


Hi I am very new to Golang, please help me. I have defined a struct inside a struct. But I get an error when I try to initialise the main struct.

type DetailsFilter struct {
  Filter struct {
    Name    string        
    ID      int                           
  } 
}

var M map[string]interface{}
M = make(map[string]interface{})
M["Filter"] = map[string]interface{}{"Name": "XYZ", "ID": 5}
var detailsFilter = DetailsFilter{Filter: M["Filter"]}}

The error I get is : can not use (type interface {}) as type struct in field value : need type assertion.

Please suggest a way to initialise DetailsFilter. I tried doing the method described in Initialize a nested struct in Golang, but even this is not working.


回答1:


Unfortunately if the type of a struct field is an anonymous struct, at construction time you can only initialize it by "duplicating" the anonymous struct type (specifying it again):

type DetailsFilter struct {
    Filter struct {
        Name string
        ID   int
    }
}

df := DetailsFilter{Filter: struct {
    Name string
    ID   int
}{Name: "myname", ID: 123}}
fmt.Println(df)

Output:

{Filter:{Name:myname ID:123}}

Shorter Alternative

So instead I recommend not to initialize it at construction, but rather after the zero-valued struct has been created, like this:

df = DetailsFilter{}
df.Filter.Name = "myname2"
df.Filter.ID = 321
fmt.Printf("%+v\n", df)

Output:

{Filter:{Name:myname2 ID:321}}

Try it on the Go Playground.

Naming the anonymous struct type

Or don't use anonymous struct as field type at all, name the type like this:

type Filter struct {
    Name string
    ID   int
}

type DetailsFilter struct {
    Filter Filter
}

And then you can simply initialize it like this:

df := DetailsFilter{Filter: Filter{Name: "myname", ID: 123}}
fmt.Printf("%+v\n", df)

Output (try it on the Go Playground):

{Filter:{Name:myname ID:123}}



回答2:


The type of M["Filter"] to the compiler is interface{}. The type to the runtime is map[string]interface{}. Neither of those is convertable to your anonymous struct type for the Filter field.

You should define a type for filter, or just not have it at all. Why not

type DetailsFilter struct {
   Name    string        
   ID      int                           
} 

M := make(map[string]*DetailsFilter)
M["Filter"] = &DetailsFilter{"Name": "XYZ", "ID": 5}
var detailsFilter = M["Filter"]

I am not sure why you need the nested anonymous struct at all. In general it is not needed to use interface{} unless you really need to. It is usually a sign you are fighting the type system instead of embracing it.

The reason You should not use an anonymous struct like that is that there is no clean way to intialize it. You have two options:

1- Repeat the type definition in the struct literal:

x := DetailsFilter{Filter: struct {
    Name string
    ID   int
}{Name: "Foo", ID: 5}}

2- Set individual fields:

x := DetailsFilter{}
x.Filter.Name = "Foo"
x.Filter.ID = 5

It seems easier to create a real type for the nested field if you want to create them with struct literals.



来源:https://stackoverflow.com/questions/30102932/how-to-initialise-nested-structs-in-go

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!