结构嵌入和歧义消解

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

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不能指代两个不同的字段,只能指代其中一个。语言规范明确定义了具体指代哪个字段。规范中指出:

以下规则适用于选择器:

  1. 对于类型为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嵌入了basebase2,它们都有一个名为num的字段。同样,这种嵌入本身没有问题。你可以使用container.base.numcontainer.base2.num来引用这些字段。但是如果你写container.num,由于在最浅层次(深度为1)上有两个被表示为container.num的字段,选择器表达式是无效的,并且会导致编译时错误。

参考链接:https://stackoverflow.com/questions/67519749/weird-behavior-of-string-method-on-embedded-types-in-go/67520517#67520517

英文:

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.

See related: https://stackoverflow.com/questions/67519749/weird-behavior-of-string-method-on-embedded-types-in-go/67520517#67520517

huangapple
  • 本文由 发表于 2023年6月3日 21:40:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76396350.html
匿名

发表评论

匿名网友

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

确定