2 回答
TA贡献1827条经验 获得超4个赞
问题 1
编译器是正确的。它应该如何决定,其中OX.F
并Y.F
应该使用它?它不能。因此,直接调用所需的方法取决于您:要么使用
z.Y.F()
或者
z.OX.F()
编辑:至于为什么你的榜样的工作,直到你定义F
上Y
,这是中提到的规格:
对于 x 类型
T
或*T
whereT
不是指针或接口类型的值,x.f
表示最浅深度的字段或方法,T
其中存在此类f
。如果没有f
最浅的深度,则选择器表达式是非法的。
(加了重点。)
在定义方法之前,最浅的实现是OX.F
. 在你定义之后Y.F
,F
在同一层上变成了两个s,这是非法的。
问题2
同样,编译器是正确的。您已将类型Y
和嵌入OX
到Z
,而不是*Y
和*OX
。正如规范中所写,
对应指针类型
*T
的方法集是所有用receiver*T
or声明T
的方法的集合(也就是包含了的方法集T
)。
*T
具有 的所有方法T
,但不是相反。方法套OX
和Y
是空的,所以很明显,fmt.Println
只是打印他们,如果他们是任何其它种类的结构没有String()
定义的方法。
TA贡献1796条经验 获得超4个赞
Ainar-G 写出简洁的答案
对于 T 或 *T 类型的值 x,其中 T 不是指针或接口类型,xf 表示 T 中最浅深度处存在此类 f 的字段或方法。如果没有一个 f 的深度最浅,则选择器表达式是非法的。
我想补充一点
如果 S 包含匿名字段 T,则 S 和 *S 的方法集都包含接收者 T 的提升方法。 *S 的方法集还包括接收者 *T 的提升方法。
因此,如果您仅使用引用来推广诸如
fmt.Println(&z)
但这会导致选择的歧义,因为 String 方法的可能性很小,因此由于规范,选择器 String 是非法的。编译器必须抱怨,但它没有。这种行为看起来没有具体说明,只能将其解释为我认为的常见打印操作的特例。这将按预期工作
var y Y fmt.Println(&y)
这是工作示例 游乐场
- 2 回答
- 0 关注
- 189 浏览
添加回答
举报