====== Go Design Decisions ====== Decision patterns, reasoning and tradeoffs for idiomatic Go software design ===== Concurrency: sync.Map vs. map with sync.Mutex ===== Both `sync.Map` and `map` with `sync.Mutex` are concurrency-safe options in Go. The choice depends on runtime access patterns and operational requirements. ==== Example: Global Map as Registry ==== // Using sync.Map import "sync" var registry sync.Map func register(key string, value any) { registry.Store(key, value) } func get(key string) (any, bool) { return registry.Load(key) } // Using map + sync.Mutex import "sync" var ( mu sync.Mutex registry = make(map[string]any) ) func register(key string, value any) { mu.Lock() defer mu.Unlock() registry[key] = value } func get(key string) (any, bool) { mu.Lock() defer mu.Unlock() val, ok := registry[key] return val, ok } ==== When to Use What ==== Use **sync.Map** when: - You expect **high-frequency concurrent access** (many readers/writers) - The map is accessed from many goroutines over a long time - The key set is dynamic and large - You want to minimize explicit locking logic Use **map with sync.Mutex** when: - You expect **low to moderate concurrency** - The map has a **small, mostly static set of keys** - You want full control over locking and error handling - You prefer simple and readable code for initialization-time usage Both approaches are valid and safe. Choose based on expected load, not based on subjective stylistic preferences.