2 回答
TA贡献1921条经验 获得超9个赞
正如 Go 规范所说,类型 T 的方法集由接收器类型为 T 的所有方法组成,而对应指针类型 *T 的方法集由接收器类型为 *T 或 T 的所有方法组成。 这意味着 *T 的方法集包括 T 的,但不包括相反的。
出现这种区别是因为如果接口值包含指针 *T,则方法调用可以通过取消引用指针来获取值,但是如果接口值包含值 T,则方法调用没有安全的方法获取指针。(这样做将允许方法修改接口内的值的内容,这是语言规范所不允许的。)
即使在编译器可以将值的地址传递给方法的情况下,如果方法修改了值,则更改将在调用者中丢失。例如,如果 bytes.Buffer 的 Write 方法使用值接收器而不是指针,则此代码:
var buf bytes.Buffer io.Copy(buf, os.Stdin)会将标准输入复制到 buf 的副本中,而不是复制到 buf 本身中。这几乎从来都不是理想的行为。
TA贡献1836条经验 获得超13个赞
如果您有 a
T
并且它是可寻址的,您可以调用接收器类型*T
为 的方法以及接收器类型为T
的方法,因为方法调用t.Meth()
将等效于(&t).Meth()
( Calls )。如果您有 a
T
并且它不可寻址(例如,函数调用的结果,或索引到映射的结果),Go 无法获得指向它的指针,因此您只能调用具有 a 的方法的接收器类型T
,不是*T
。如果您有一个接口
I
,并且I
的方法集中的部分或全部方法由接收器为 的方法提供*T
(其余方法由接收器为 的方法提供T
),则*T
满足接口I
,但T
不满足。那是因为*T
的方法集包括T
's,但不是相反的(再次回到第一点)。
简而言之,您可以混合和匹配带有值接收器的方法和带有指针接收器的方法,并将它们与包含值和指针的变量一起使用,而不必担心哪个是哪个。两者都可以使用,并且语法相同。然而,如果需要带有指针接收器的方法来满足接口,那么只有一个指针可以分配给接口——一个值将是无效的。
- 2 回答
- 0 关注
- 136 浏览
添加回答
举报