Reputation: 446
I am a little confused with a behavior of Go regarding variable 'overriding' in embedded structure.
First situation
If a child
structure embeds a parent
structure containing a field Attr
, I can access the value of Attr indifferently with child.Attr
or child.parent.Attr
. Here is an example :
package main
import (
"fmt"
"encoding/json"
)
type parent struct {
Attr int `json:"attr"`
}
type child struct {
parent
}
func main() {
var c child
json.Unmarshal([]byte(`{"i": 1}`), &c)
fmt.Println(c.Attr)
fmt.Println(c.parent.Attr)
}
Second situation
However, if the child structure contains itself a field named Attr
, those two fields are different and can be accessed separately, as shows the following example :
package main
import (
"fmt"
"encoding/json"
)
type parent struct {
Attr int `json:"attr"`
}
type child struct {
parent
Attr int
}
func main() {
var c child
json.Unmarshal([]byte(`{"attr": 1}`), &c)
fmt.Println(c.Attr)
fmt.Println(c.parent.Attr)
}
I am very surprised that this implicit behavior is allowed in golang. I would have expected the language to be stricter as it is on so many points. Besides, I wasn't able to find a clear specification about this. Is it just a side-effect or can I use that feature?
Upvotes: 1
Views: 549
Reputation: 1380
Golang specification actually states how embedded fields are resolved
A selector f may denote a field or method f of a type T, or it may refer to a field or method f of a nested embedded field of T. The number of embedded fields traversed to reach f is called its depth in T. The depth of a field or method f declared in T is zero. The depth of a field or method f declared in an embedded field A in T is the depth of f in A plus one.
Then...
For a value x of type T or *T where T is not a pointer or interface type, x.f denotes the field or method at the shallowest depth in T where there is such an f. If there is not exactly one f with shallowest depth, the selector expression is illegal.
Upvotes: 5