Understanding go nested structs

I'm trying to understand nested structs in go, so I made a little test: (playground)

type A struct {
    a string
}

type B struct {
    A
    b string
}

func main() {
    b := B{A{"a val"}, "b val"}

    fmt.Printf("%T -> %v\n", b, b)   // B has a nested A and some values 
    // main.B -> {{a val} b val}

    fmt.Println("b.b ->", b.b)       // B's own value
    // b.b -> b val

    fmt.Println("b.A.a ->", b.A.a)   // B's nested value
    // b.a -> a val

    fmt.Println("b.a ->", b.a)       // B's nested value? or own value?
    // b.a -> a val
}

So how and why the last two lines work? Are they are same? Which should I use?

Upvotes: 3

Views: 1089

Answers (1)

Ainar-G
Ainar-G

Reputation: 36189

They are the same. See the Go Spec on selectors:

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.

Note that this means that b.a is illegal if type B embeds two types with the same field on the same depth:

type A1 struct{ a string }
type A2 struct{ a string }
type B struct {
    A1
    A2
}

// ...
b := B{A1{"a1"}, A2{"a2"}}
fmt.Println(b.a) // Error: ambiguous selector b.a

Playground: http://play.golang.org/p/PTqm-HzBDr.

Upvotes: 5

Related Questions