零值 sync.Mutex 和 sync.RWMutex 是有效的,所以指向 mutex 的指针基本是不必要的。
// Bad
mu := new(sync.Mutex)
mu.Lock()
// Good
var mu sync.Mutex
mu.Lock()
Mutex 作为其他结构体一个字段时,应该使用值而不是指针。即使该结构体不被导出,也不要直接把 Mutex 嵌入到结构体中。
// Bad
type sMap struct {
sync.Mutex
data map[string]string
}
func NewSMap() *sMap {
return &sMap{
data: make(map[string]string),
}
}
func (m *sMap) Get(k string) string {
m.Lock()
defer m.Unlock()
return m.data[k]
}
// Good
type sMap struct {
mutex sync.Mutex
data map[string]string
}
func NewSMap() *sMap {
return &sMap{
data: make(map[string]string),
}
}
func (m *SMap) Get(k string) string {
m.mutex.Lock()
defer m.mutex.Unlock()
return m.data[k]
}
Bad 部分会导致字段 Mutex、Lock 和 Unlock 方法是 sMap 导出的字段和 API,但又没有明确说明,既导致了模糊的文档,又泄露了 sMap 的实现细节。Good 部分可以做到字段 mutex 及其方法是 sMap 的实现细节,对其调用者不可见。