Go 中基类型方法指针的选择器

很明显,下面的代码可以正常工作:


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

}


但正如我从规范中看到的:


对于 T 或 *T 类型的值 x(其中 T 不是指针或接口类型),xf 表示 T 中最浅深度处存在 f 的字段或方法。如果不存在恰好一个深度最浅的 f,则选择器表达式是非法的。


但在示例中M不是来自*T,而是来自T。我知道其中*T包括 的方法集T,但正如我所见,规范并没有告诉我们有关 的方法集*T。我是否理解带有注释的行的规范错误或正确性是基于其他规范规则?


largeQ
浏览 96回答 2
2回答

波斯汪

你引用:x.f表示最浅深度的字段或方法T引文指的是深度。深度的“定义”是:选择器可以表示类型的f字段或方法,也可以指的嵌套嵌入字段的字段或方法。遍历到达的嵌入字段的数量称为它的深度。中声明的字段或方法的深度为零。在嵌入字段in中声明的字段或方法的深度是in的深度加一。fTfTfTfTfATfA关键是嵌入。您的结构不嵌入单一类型。所以根据定义, your的深度T.M为零。您的t变量是类型*T(即表达式的类型&T{},它采用结构复合文字的地址:它生成一个指向用文字值初始化的唯一变量的指针)。并引用规范:方法值:与选择器一样,使用指针对具有值接收器的非接口方法的引用将自动取消对该指针的引用:pt.Mv相当于(*pt).Mv。t.M是对非接口方法 的引用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.Mand T2.M。但由于 的 深度T2.T.M是1, 的 深度T2.M是0,T2.M处于 中最浅的深度T2,因此t2.M将表示T2.M且 not ,因此上面的示例打印(在Go PlaygroundT2.T.M上尝试):T2.M()

四季花海

来自方法集:对应指针类型*T的方法集是用接收者*T或T声明的所有方法的集合(即也包含T的方法集)。
打开App,查看更多内容
随时随地看视频慕课网APP