在 go 中,当 key 不存在时,map 的值是零值。我在下面有一个简短的代码片段: 操场
package main
import (
"sync"
)
func main() {
var mm map[int]sync.Mutex
var m sync.Mutex
mm[1].Lock() // not work due to cannot call pointer method on mm[1] and cannot take the address of mm[1]
m.Lock() // work normal
}
Run Code Online (Sandbox Code Playgroud)
mm[1]和m上面有什么区别?我用reflect来检查,但看不出它们之间的区别。关于导致差异的任何线索?
The issue is not about the zero value of a map, it's about addressability during methods calls.
The Lock method on a mutex has a pointer receiver:
func (*Mutex) Lock
Run Code Online (Sandbox Code Playgroud)
Given the variable m sync.Mutex, calling a method on it with a pointer receiver will automatically turn into &m.Lock(), per the spec:
A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()
The important part of this is the addressable requirement. The variable m is addressable, but the returned value of a map lookup is not. This means that the compiler will not attempt to call &mm[1].Lock().
These can be seen in the error messages returned when you attempt to compile your example:
./prog.go:11:7: cannot call pointer method on mm[1]
./prog.go:11:7: cannot take the address of mm[1]
Run Code Online (Sandbox Code Playgroud)