问题
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