1 回答
TA贡献1817条经验 获得超14个赞
如果在结构中嵌入类型,则嵌入类型的字段和方法将提升为嵌入类型。它们“作用”就像在嵌入器类型上定义一样。
这是什么意思?如果类型嵌入类型,并且类型有一个方法,你可以调用类型(接收方仍然是,这不是继承也不是虚方法)。A
B
B
String()
String()
A
B
目前为止,一切都好。但是,如果类型嵌入了类型和类型,两者都有一个方法呢?然后会模棱两可,因此在这种情况下,该方法将不会被推广。A
B
C
String()
A.String()
String()
这解释了您的经历。打印将具有默认格式(结构字段),因为将有 2 种方法,因此没有一个用于其自身。当然,默认格式设置涉及打印字段,并且为了生成值的默认表示形式,包会检查正在打印的值是否实现 ,如果是,则调用其方法。Engineer
String()
Engineer
string
fmt
fmt.Stringer
String()
如果删除 ,则只有一个方法被提升,from ,因此该方法由包调用以生成值本身的表示形式。Person.String()
String()
TaxPlayer
fmt
string
Engineer
同样,如果你删除 :那么将是唯一提升的方法,所以它用于值本身。TaxPayer.String()
Person.String()
String()
Engineer
这在 Spec: 结构类型中有详细说明:
如果结构中嵌入字段的字段或方法是表示该字段或方法的合法选择器,则称为升级。
f
x
x.f
f
[...]给定一个结构类型和一个定义的类型,升级的方法包含在结构的方法集中,如下所示:
S
T
如果包含一个嵌入字段,则 方法集 和 两者都包括带有接收器的提升方法。的方法集还包括带有接收器的提升方法。
S
T
S
*S
T
*S
*T
如果包含一个嵌入字段,则 的方法集 和 两者都包括带有 receiver 或 的升级方法。
S
*T
S
*S
T
*T
第一句说“如果x.f
是法定选择器”。法律是什么意思?
x.f表示值 的字段或方法。
f
x
[...]选择器可以表示某种类型的字段或方法,也可以引用 嵌套嵌入字段 的字段或方法。遍历以达到的嵌入场的数量称为 其深度在 中。中声明的字段或方法的深度为零。在 嵌入的字段中声明的字段或方法 f 的深度是 in 加一的深度。
f
f
T
f
T
f
T
f
T
A
T
f
A
以下规则适用于选择器:
对于类型或 where 的值不是指针或接口类型,表示存在此类 .如果深度不正好有一个
f
,则选择器表达式是非法的。x
T
*T
T
x.f
T
f
[...]
强调了本质,并解释了为什么首先没有调用任何方法:可能来自2个“源”:和,因此是非法的选择器,因此没有一个方法将是方法集的一部分。String()
Engineer.String()
Person.String
TaxPayer.String
Engineer.String
String()
Engineer
使用非法选择器会引发编译时错误(例如“不明确的选择器工程师。福”)。因此,您收到错误,因为您显式尝试引用 。但是仅仅嵌入2种类型都有,这不是编译时错误。嵌入本身不是错误。使用非法选择器将是错误。如果你写 ,那会再次引发编译时错误。但是如果你只是通过打印:,这里没有非法的选择器,你就不参考了。这是允许的。(当然,由于方法集 没有提升的方法,因此只有在打印字段时才会调用它来生成 – 的字符串表示形式。engineer.Foo
String()
engineer.String()
engineer
fmt.Println(engineer)
engineer.String()
Engineer
String()
Engineer
- 1 回答
- 0 关注
- 95 浏览
添加回答
举报