Golang方法集(指针与值接收器)

use*_*187 5 go

我很难理解为什么这些规则与指针类型.vs的方法集相关联.值类型

有人可以解释一下原因(从界面表的角度来看)

(William Kennedy博客的片段)

Values          Methods Receivers
-----------------------------------------------
T               (t T)
*T              (t T) and (t *T)

Methods Receivers    Values
-----------------------------------------------
(t T)                 T and *T
(t *T)                *T
Run Code Online (Sandbox Code Playgroud)

来自规范的片段

方法集

类型可以具有与其关联的方法集.接口类型的方法集是其接口.任何其他类型T的方法集由用接收器类型T声明的所有方法组成.相应指针类型*T的方法集是用receiver*T或T声明的所有方法的集合(也就是说,它还包含方法一套T).其他规则适用于包含匿名字段的结构,如结构类型一节中所述.任何其他类型都有一个空方法集.在方法集中,每个方法必须具有唯一的非空方法名称.

类型的方法集确定类型实现的接口以及可以使用该类型的接收器调用的方法.

hob*_*bbs 17

  1. 如果你有一个*T你可以调用具有接收器类型的*T方法以及具有接收器类型的方法T(你引用的段落, 方法集).
  2. 如果你有一个T并且它是可寻址的,你可以调用具有接收器类型的*T方法以及具有接收器类型T的方法,因为方法调用t.Meth()将等同于(&t).Meth()(调用).
  3. 如果你有一个T并且它不可寻址,你只能调用接收器类型为的方法T,而不是*T.
  4. 如果你有一个接口I,并且I方法集中的部分或全部方法都是由带有接收器的方法提供的*T(其余部分由带有接收器的方法提供T),则*T满足接口I,但T不满足.那是因为*T方法集包括T's,但不是相反(再次回到第一点).

简而言之,您可以使用指针接收器将值接收器和方法混合和匹配,并将它们与包含值和指针的变量一起使用,而不必担心哪个是哪个.两者都有效,语法也一样.但是,如果需要具有指针接收器的方法来满足接口,那么只有一个指针可以分配给接口 - 一个值将无效.

  • 感谢水晶般清晰的解释。希望文档能如此清晰 (2认同)

小智 7

来自Golang 常见问题解答

正如 Go 规范所说,类型 T 的方法集由接收者类型为 T 的所有方法组成,而对应的指针类型 *T 的方法集由接收者类型为 *T 或 T 的所有方法组成。这意味着 *T 的方法集包括T,但不包括T。

出现这种区别的原因是,如果接口值包含指针 *T,则方法调用可以通过取消引用指针来获取值,但如果接口值包含值 T,则方法调用没有安全的方法来获取指针。(这样做将允许方法修改接口内的值的内容,这是语言规范不允许的。)

即使编译器可以将值的地址传递给方法,如果方法修改了值,则调用者中的更改也会丢失。例如,如果 bytes.Buffer 的 Write 方法使用值接收器而不是指针,则以下代码:

var buf bytes.Buffer
io.Copy(buf, os.Stdin)
Run Code Online (Sandbox Code Playgroud)

会将标准输入复制到 buf 的副本中,而不是复制到 buf 本身。这几乎从来都不是理想的行为。

关于底层的 Golang 接口。