go.concurrent_map_access
Correctness
Critical
Detects concurrent access to maps without proper synchronization, which causes fatal runtime panics.
Why It Matters
Section titled “Why It Matters”Concurrent map access causes:
- Fatal panics — Concurrent map read/write is a fatal error in Go
- Service crashes — No recovery possible from this panic
- Intermittent failures — Only manifests under load
- Hard to reproduce — Depends on goroutine timing
Example
Section titled “Example”// ❌ Before (concurrent access)var cache = make(map[string]interface{})
func handler(w http.ResponseWriter, r *http.Request) { key := r.URL.Query().Get("key") cache[key] = "value" // Fatal error if concurrent!}// ✅ After (sync.Map)var cache sync.Map
func handler(w http.ResponseWriter, r *http.Request) { key := r.URL.Query().Get("key") cache.Store(key, "value") // Thread-safe}What Unfault Detects
Section titled “What Unfault Detects”- Map writes in goroutines
- Map access in HTTP handlers (implicitly concurrent)
- Missing mutex protection on maps
- Maps shared across goroutines
Auto-Fix
Section titled “Auto-Fix”Unfault generates thread-safe alternatives:
// Option 1: sync.Map (best for many goroutines, infrequent writes)var cache sync.Map
// Option 2: RWMutex (best for frequent reads, rare writes)type SafeMap struct { mu sync.RWMutex data map[string]interface{}}
func (m *SafeMap) Get(key string) interface{} { m.mu.RLock() defer m.mu.RUnlock() return m.data[key]}
func (m *SafeMap) Set(key string, val interface{}) { m.mu.Lock() defer m.mu.Unlock() m.data[key] = val}