如果S包含匿名字段T,S的方法集是否包括带接收器*T的提升方法?

tar*_*lah 5 go

这个问题的标题几乎是从golang规范中引用的:

给定结构类型S和名为T的类型,提升的方法包含在结构的方法集中,如下所示:

  • 如果S包含匿名字段T,则S和*S的方法集都包括具有接收方T的提升方法.*S的方法集还包括具有接收方*T的提升方法.

这是一个go操场,显示该方法inc()被提升.

package main

import (
    "fmt"
)

// just an int wrapper
type integer struct {
    i int
}

func (self *integer) inc() {
    self.i++
}

type counter struct {
    integer
}

func main() {
    c := counter{}

    c.inc()
    fmt.Println(c)
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*erg 7

没有*T的方法不会被提升.规范没有明确允许它,因此不允许.但是,这背后有一个原因.

有时您可以在T上调用*T方法.但是,有一个隐式引用.*T的方法不被视为T方法集的一部分.

从Go规范的调用部分:

如果x是可寻址的并且&x的方法集包含m,则xm()是(&x).m()的简写

从Go规范的地址运算符部分:

对于类型为T的操作数x,地址操作&x生成类型为*T到x的指针.操作数必须是可寻址的,即,变量,指针间接或切片索引操作; 或可寻址结构操作数的字段选择器; 或者可寻址数组的数组索引操作.作为可寻址性要求的例外,x也可以是(可能带括号的)复合文字.

如果S包含*T,您甚至不需要获取其地址,因此可以调用方法.如果*S包含T,则知道T是可寻址的,因为T是指向间接结构的字段选择器.对于包含T的S,这不能保证.


更新:为什么该代码有效?

请记住,*S包含*T的方法集.另外,正如我之前引用的那样:

如果x是可寻址的并且&x的方法集包含m,则xm()是(&x).m()的简写

将两者放在一起,你就得到了答案.计数器是可寻址的,&计数器包含*T的方法集.因此,counter.Inc()是(&counter).Inc()的简写.