Обрабатывать каждое поле структуры как независимое с целью блокировки. Дано:
type Foo struct {
stringMap map[string]string
strings []string
numbers []float64
}
Следующее безопасно:
foo := &Foo{}
/* ... */
go func() {
foo.stringMap["foo"] = "bar"
}()
go func() {
foo.strings[0] = "baz"
}()
go func() {
fmt.Println(foo.numbers[0])
}()
Но это небезопасно:
go func() {
fmt.Println(foo.numbers[0])
}()
go func() {
foo.numbers = append(foo.numbers, 123.456)
}()
Так что вы обычно хотите один мьютекс для каждого поля, или каждая группа полей, которые могут быть изменены вместе:
type Foo struct {
stringMapMu sync.Mutex
stringMap map[string]string
stringsMu sync.Mutex
strings []string
numbersMu sync.Mutex
numbers []float64
}
Тогда:
go func() {
foo.numbersMu.Lock()
defer foo.numbersMu.Unlock()
fmt.Println(foo.numbers[0])
}()
go func() {
foo.numbersMu.Lock()
defer foo.numbersMu.Unlock()
foo.numbers = append(foo.numbers, 123.456)
}()