我试图通过围棋官方巡回赛来学习围棋,但我发现the section on value vs pointer receivers种围棋的后半部分令人困惑:

In general, all methods on a given type should have either value or pointer receivers, but not a mixture of both. (We'll see why over the next few pages.)

基本上,我有两个问题:

A)我似乎找不到为什么我们不应该在本章的其余部分混合使用这两种类型的接收器的原因,所以如果有人可以解释或参考讨论这一问题的部分,我将不胜感激.

B)假设混合使用指针和值接收器确实是一个坏主意,那么如何实现不同的接口呢?例如,我发现教程描述了两个不同的内置接口,即Stringererror.在提供的代码中,Stringera value receiver is used和切换到指针接收器似乎不起作用,而在error接口中,a pointer receiver is used.如何在不违反上述原则的情况下为 struct 实现这两个接口?

注意,我已经研究过类似的问题,关于使用值接收器与指针接收器的缺点,如对象创建,以及保持一致性的重要性(从这question开始),但由于我是真正的初学者,我试图仅结合Go官方巡回赛中的信息/示例来说明这些问题.

谢谢!

推荐答案

对于第一个问题,同时拥有值接收器和指针接收器可能会导致微妙的竞争,因为值接收器复制对象.例如:

type T struct {
  field int
}

func (T) ValueReceiver() int {return 1}

func (t *T) SetField(i int) {t.field=i}

在上面的例子中,如果你同时呼叫SetFieldValueReceiver,你就会有一场比赛.这是因为当SetField向场写入时,ValueReceiver正在创建接收器的副本,从而导致在没有任何显式同步的情况下读取相同的场.

对于第二个问题:如果您有修改T的方法,那么让所有方法都使用指针接收器是有意义的.这样,您就可以防止微妙的竞争,并实现所有接口T将.

这是关于这个主题的常见问题的链接(感谢@jub0bs):

https://go.dev/doc/faq#methods_on_values_or_pointers

Go相关问答推荐

Websocket服务器实现与x/net库trowing 403

Go中的Slice[:1][0]与Slice[0]

Go-如何在递归函数中关闭通道

通过 Terraform 中的 MapNestedAtribute 进行迭代

是否可以将 http.ServeHttp 包装在 go 中以使用 alexedwards/scs/v2 添加会话

如何在 Go 中将 int 转换为包含 complex128 的泛型类型?

golang 上基于标头的版本控制

闭包所处的环境范围是什么?

如何匹配两次出现的相同但随机字符串之间的字符

无法使用 gocsv 读取引用字段

Go 信号处理程序不处理终端窗口关闭

emersion/go-imap - imap.FetchRFC822:无效内存地址或零指针取消引用

如何将一片 map 转换为一片具有不同属性的 struct

Dockerfile 问题 - 为什么找不到二进制 dlv - 没有这样的文件或目录

Golang - 客户 Unmarshaler/Marshaler 在指针上具有 nil/null 值

Go 中 SDL Surface 的 OpenGL 纹理

如何使路径/不匹配 Golang net/http 中所有其他不匹配的路径

Go/Golang:如何从 big.Float 中提取最低有效数字?

Gorilla/Mux 和 Websocket 竞赛条件,这安全吗?

是否可以动态加载 Go 代码?