英文:
Golang: Why selector to pointers is illegal after comparison?
问题
我正在阅读有关选择器的规范:https://golang.org/ref/spec#Selectors
为什么 q.M0()
是无效的,而 p.M0()
是有效的,且 q=p
。对我来说非常奇怪。
相关的源代码:
type T0 struct {
x int
}
func (*T0) M0()
type T1 struct {
y int
}
func (T1) M1()
type T2 struct {
z int
T1
*T0
}
func (*T2) M2()
type Q *T2
var t T2 // with t.T0 != nil
var p *T2 // with p != nil and (*p).T0 != nil
var q Q = p
p.M0() // ((*p).T0).M0() M0 expects *T0 receiver
q.M0() // (*q).M0 is valid but not a field selector
英文:
I'm reading the spec about selectors: https://golang.org/ref/spec#Selectors
Why q.M0()
is invalid. While p.M0()
is valid and q=p
. Very strange for me.
The relevant source code:
type T0 struct {
x int
}
func (*T0) M0()
type T1 struct {
y int
}
func (T1) M1()
type T2 struct {
z int
T1
*T0
}
func (*T2) M2()
type Q *T2
var t T2 // with t.T0 != nil
var p *T2 // with p != nil and (*p).T0 != nil
var q Q = p
p.M0() // ((*p).T0).M0() M0 expects *T0 receiver
q.M0() // (*q).M0 is valid but not a field selector
答案1
得分: 7
为什么 q.M0()
是无效的,而 p.M0()
是有效的,且 q=p
?对我来说非常奇怪。
q
被初始化为 var q Q = p
,但这并不意味着它们相等。这个赋值操作是有效的,因为它没有违反可赋值性规则,但是 q
的类型与 p
的类型不同。
q
的类型是 Q
(其中 type Q *T2
),而 p
的类型是 *T2
。
在 Go 语言中,方法属于特定的类型。当你这样做时:
type Q *T2
它创建了一个名为 Q
的新类型(*T2
是其底层类型)。这个新类型没有任何方法,它不会从 *T2
中“继承”任何方法,因此 q.M0()
将在编译时出错:
> q.M0 undefined (type Q has no field or method M0)
注意:
你可能仍然觉得奇怪,因为 M0()
的声明如下:
func (*T0) M0()
它具有 *T0
的接收器,因此它属于类型 *T0
,然而 p
的类型是 *T2
,所以 *T2
不应该有这个 M0()
方法,因此 p.M0()
也应该是无效的。但是 T2
是一个结构体,它嵌入了 *T0
,所以 *T0
的方法被_提升_了,并且它们将在 T2
的方法集中。
还可以参考这个相关的问题:https://stackoverflow.com/questions/40803654/golang-why-selector-to-pointers-is-illegal-after-comparison/40804236#40804236
英文:
> Why q.M0()
is invalid. While p.M0()
is valid and q=p
. Very strange for me.
q
is initialized like var q Q = p
, but it does not mean they are equal. The assignment is valid because it does not violate the assignability rules, but type of q
is different than type of p
.
Type of q
is Q
(where type Q *T2
), and type of p
is *T2
.
In Go, methods belong to a specific type. When you do this:
type Q *T2
It creates a new type named Q
(*T2
being its underlying type). The new type will have 0 methods, it does not "inherit" any methods from *T2
, hence q.M0()
will be a compile-time error:
> q.M0 undefined (type Q has no field or method M0)
Note:
You may still think it's strange because M0()
is declared like this:
func (*T0) M0()
It has *T0
receiver so it belongs to the type *T0
, yet type of p
is *T2
, so *T2
should not have this M0()
method and therefore p.M0()
should also be invalid. But T2
is a struct which embeds *T0
, and so methods of *T0
are promoted, and they will be in the method set of T2
.
Also see this related question: https://stackoverflow.com/questions/40803654/golang-why-selector-to-pointers-is-illegal-after-comparison/40804236#40804236
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论