====== 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.