In the Go documentation for xml:Unmarshal there is an example that unmarshals this xml
<Person>
<FullName>Grace R. Emlin</FullName>
<Company>Example Inc.</Company>
<Email where="home">
<Addr>[email protected]</Addr>
</Email>
<Email where='work'>
<Addr>[email protected]</Addr>
</Email>
<Group>
<Value>Friends</Value>
<Value>Squash</Value>
</Group>
<City>Hanga Roa</City>
<State>Easter Island</State>
</Person>
using these structs
type Address struct {
City, State string
}
type Result struct {
XMLName xml.Name `xml:"Person"`
Name string `xml:"FullName"`
Phone string
Email []Email
Groups []string `xml:"Group>Value"`
Address
}
Note that Result
contains a reference to the separately defined Address
. Obviously, this code works.
When I try to unmarshal this xml
<C>
<D>
<E>Fred</E>
<F>42</F>
</D>
</C>
using these structs
type D struct {
E string
F int
}
type C struct { // Compiles OK but result empty.
D
}
I get empty results {{ 0}}
. However the struct below works OK producing {{Fred 42}}
type C struct { // This works.
D struct {
E string
F int
}
}
See Playground example.
Am I missing some subtle point about structs?
When you do this:
type C struct {
D
}
This is called embedding (D
is an anonymous field or embedded field). You may think of this as if the fields (and methods) of the embedded type become part of the embedder type (they get promoted). So in this case it's "legal" to write C.E
and C.F
.
When you do:
type C struct {
D struct {
E string
F int
}
}
This is not embedding (or "nesting"). Here D
is a "regular", named field of the C
type. D
is the name of the field, which is followed by an anonymous type literal, the type of the field. Here it is not legal to write C.E
nor C.F
, only C.D.E
and C.D.F
. And this is the proper mapping of the XML structure you try to unmarshal, hence this works (try it on the Go Playground).
Note that if you change the embedding to a regular field, it will also work (try it on the Go Playground):
type C struct {
D D
}
Also note that you can skip the whole D
wrapper struct if you specify the XML element paths in the field tags:
type C struct {
E string `xml:"D>E"`
F int `xml:"D>F"`
}
Try it on the Go Playground.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With