很明显,下面的代码可以正常工作:
package main
import "fmt"
type T struct {
a int
}
func (t T) M() {
fmt.Println("M method")
}
func main() {
var t = &T{1}
t.M() // it's interesting
}
但正如我从 specification 中看到的那样:
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.
但在示例中,M
不是来自 *T
,而是来自 T
。我知道 *T
包含 T
的方法集,但正如我所见,规范没有告诉我们有关 *T
的方法集。我是否理解带注释的行的规范错误或正确性是基于其他规范规则?
最佳答案
你引用了:
x.f
denotes the field or method at the shallowest depth inT
引用是指深度。 "Definition" of depth is:
A selector
f
may denote a field or methodf
of a typeT
, or it may refer to a field or methodf
of a nested embedded field ofT
. The number of embedded fields traversed to reachf
is called its depth inT
. The depth of a field or methodf
declared inT
is zero. The depth of a field or methodf
declared in an embedded fieldA
inT
is the depth off
inA
plus one.
关键是嵌入。您的结构不嵌入单一类型。因此,根据定义,您的TM
深度是零。
您的 t
变量的类型为 *T
(即 &T{}
表达式的类型,即 taking the address of结构 composite literal :它生成一个指向用文字值初始化的唯一变量的指针。
As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer:
pt.Mv
is equivalent to(*pt).Mv
.
t.M
是对非接口(interface)方法 T.M
的引用,由于 t
是指针,因此会自动取消引用:(*t).M()
.
现在让我们看一个例子,其中“最浅深度”确实很重要。
type T struct{}
func (t T) M() { fmt.Println("T.M()") }
type T2 struct {
T // Embed T
}
func (t T2) M() { fmt.Println("T2.M()") }
func main() {
var t T = T{}
var t2 T2 = T2{T: t}
t2.M()
}
在main()
中,我们调用t2.M()
。由于 T2
嵌入 T
,因此可以引用 T2.T.M
和 T2.M
。但由于 T2.T.M
的深度为 一,而 T2.M
的深度为 零,因此 T2 .M
位于 T2
中最浅的深度,因此 t2.M
将表示 T2.M
而不是 T2 .T.M
,所以上面的示例打印(在 Go Playground 上尝试):
T2.M()
关于go - Go 中基类型方法指针的选择器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57747668/