Sobes.tech
Middle

Is the map data structure in Go safe?

sobes.tech AI

Answer from AI

No, the standard map in Go is not thread-safe for concurrent read and write access.

Attempting to perform simultaneous writes or a combination of reads and writes from multiple goroutines to the same map without external synchronization will result in a race condition, which can lead to unpredictable behavior or a panic.

To ensure thread safety when accessing a map concurrently, you can use:

  • sync.Mutex or sync.RWMutex for manual locking.
  • sync.Map (introduced in Go 1.9) for more specialized scenarios where there are frequent writes and rarely changing elements.

Example of using sync.Mutex:

package main

import (
	"fmt"
	"sync"
)

type SafeMap struct {
	mu sync.Mutex
	m  map[string]int
}

func (sm *SafeMap) Add(key string, value int) {
	sm.mu.Lock() // Acquire the mutex before writing
	defer sm.mu.Unlock() // Release the mutex after completion
	sm.m[key] = value
}

func (sm *SafeMap) Get(key string) (int, bool) {
	sm.mu.Lock() // Acquire the mutex before reading
	defer sm.mu.Unlock() // Release the mutex after completion
	val, ok := sm.m[key]
	return val, ok
}

func main() {
	sm := SafeMap{m: make(map[string]int)}

	var wg sync.WaitGroup
	go func() {
		wg.Add(1)
		defer wg.Done()
		sm.Add("key1", 1)
	}()
		go func() {
		wg.Add(1)
		defer wg.Done()
		sm.Add("key2", 2)
	}()

	wg.Wait()
	fmt.Println(sm.Get("key1")) // Safe read
}