Thread-Safe Maps
In Go, maps are not safe for concurrent use. If one goroutine is writing to a map while another is reading from or writing to it, the program will crash with a fatal error: concurrent map writes.
The Problem
m := make(map[string]int)
// This will eventually crash if run on multiple cores
go func() { m["key"] = 1 }()
go func() { fmt.Println(m["key"]) }()
The Solution: Wrapping in a Struct
The standard way to make a map thread-safe is to wrap it in a struct along with a mutex.
type safeMap struct {
mu sync.Mutex
data map[string]int
}
func (s *safeMap) Set(key string, val int) {
s.mu.Lock()
defer s.mu.Unlock()
s.data[key] = val
}
func (s *safeMap) Get(key string) int {
s.mu.Lock()
defer s.mu.Unlock()
return s.data[key]
}
By ensuring that every read and write operation is protected by the same mutex, you guarantee that only one goroutine touches the map at any given time.