当你有一个带有像这样的值接收器的方法时:
func (RPC) version() int {
return 1 // never going to need to change this
}
你调用这个方法:
version := rpc.version() // grab some other information while we're waiting
必须从该值制作副本rpc
,它将传递给方法(用作接收者值)。
所以当一个 goroutinego rpc.compute()
正在运行并正在修改rpc
结构体值(rpc.result = 42
),主 goroutine 正在复制整个rpc
结构值。那里!这是一场比赛。
当你修改接收者类型为指针时:
func (*RPC) version() int {
return 1 // never going to need to change this
}
你调用这个方法:
version := rpc.version() // grab some other information while we're waiting
这是一个简写
version := (&rpc).version()
这传递了地址rpc
价值RPC.version()
,它仅使用指针作为接收者,因此不会复制rpc
结构值。由于结构中没有任何内容被使用/读入RPC.version()
,没有种族。
Note:
请注意,如果RPC.version()
会读到RPC.result
字段,这也将是一场竞赛,因为一个 Goroutine 会修改它,而主 Goroutine 会读取它:
func (rpc *RPC) version() int {
return rpc.result // RACE!
}
Note #2:
另请注意,如果RPC.version()
会阅读另一个领域RPC
没有被修改RPC.compute()
,这不会是一场比赛,例如:
type RPC struct {
result int
done chan struct{}
dummy int
}
func (rpc *RPC) version() int {
return rpc.dummy // Not a race
}