英文:
Struct embedding and ambiguity resolution
问题
在Golang的结构嵌入中,我遇到了一个歧义。嵌入的结构体有一个字段num,而容器结构体也有一个字段num。
type base struct {
	num int
}
type container struct {
	base
	str string
	num int
}
在引用时,它的解析如下,这样使用合法和正确吗?
container.num - 解析为外部
&
container.base.num - 解析为内部
英文:
In Golang structure embedding I have created an ambiguity. Embedded struct have and field num, and container struct too have a field num.
type base struct {
	num int
}
type container struct {
	base
	str string
	num int
}
While referencing, it resolved as follows, and is it legal and correct use?
container.num - resolved to outer
&
container.base.num - resolved to inner
答案1
得分: 2
嵌入类型的字段和方法会被提升,如果选择器表达式不含糊,你可以使用它。如果嵌入类型的结构体中也有与被提升的字段同名的字段,也不会有问题,但是显然container.num不能指代两个不同的字段,只能指代其中一个。语言规范明确定义了具体指代哪个字段。规范中指出:
以下规则适用于选择器:
- 对于类型为
T或*T的值x,其中T不是指针类型或接口类型,x.f表示在T的最浅层次上存在f的字段或方法。如果最浅层次上不止一个f,则选择器表达式是非法的。 
所以在你的例子中,最浅层次是container.num,而不是container.base.num。这里没有歧义。
再看一个例子:
type base struct {
    num int
}
type base2 struct {
    num int
}
type container struct {
    base
    base2
    str string
}
container嵌入了base和base2,它们都有一个名为num的字段。同样,这种嵌入本身没有问题。你可以使用container.base.num和container.base2.num来引用这些字段。但是如果你写container.num,由于在最浅层次(深度为1)上有两个被表示为container.num的字段,选择器表达式是无效的,并且会导致编译时错误。
英文:
Embedding is never a problem. Fields and methods of the embedded type get promoted, and if the selector expression is not ambiguous, you may use it.
If the embedder type also has a field name the same as a field that could get promoted, that's also not a problem, but obviously container.num can't designate 2 different fields, only one. The language spec properly defines what that will be. Spec: Selectors:
> The following rules apply to selectors:
> 1. 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.
>
> [...]
So the "shallowest" in your case is container.num, not container.base.num. No ambiguity here.
Let's see another example;
type base struct {
	num int
}
type base2 struct {
	num int
}
type container struct {
	base
	base2
	str string
}
container embeds base and base2, and both have a field named num. Again, this embedding itself is not a problem. You can also refer to those fields using container.base.num and container.base2.num. But if you'd write container.num, since there are not one (but 2) fields denoted by container.num at the shallowest depth (depth = 1), the selector expression is invalid and would result in a compile-time error.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论