理解嵌套的Go结构体

huangapple go评论75阅读模式
英文:

Understanding go nested structs

问题

我正在尝试理解Go语言中的嵌套结构体,所以我做了一个小测试:(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有一个嵌套的A和一些值
    // main.B -> {{a val} b val}

    fmt.Println("b.b ->", b.b)       // B自己的值
    // b.b -> b val

    fmt.Println("b.A.a ->", b.A.a)   // B的嵌套值
    // b.a -> a val

    fmt.Println("b.a ->", b.a)       // B的嵌套值?还是自己的值?
    // b.a -> a val
}

那么最后两行代码是如何工作的?它们是相同的吗?我应该使用哪一个?

英文:

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?

答案1

得分: 5

它们是相同的。请参阅Go规范中的选择器

对于类型为T*T的值x,其中T不是指针类型或接口类型,x.f表示在T中最浅深度的位置上存在的字段或方法f。如果最浅深度上不止一个f,则选择器表达式是非法的。

请注意,这意味着如果类型B嵌入了两个具有相同字段的类型,并且在相同的深度上,那么b.a是非法的:

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) // 错误:模棱两可的选择器 b.a

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

英文:

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.

huangapple
  • 本文由 发表于 2015年10月22日 22:00:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/33282897.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定