What is a map in Go and is it safe for concurrent use?
Learn what a Go map is, why it is not safe for concurrent writes, and how to guard it with sync.RWMutex or sync.Map — with code examples.
Expected Interview Answer
A map in Go is a built-in hash table that stores unordered key-value pairs with average O(1) lookup, insert, and delete. It is NOT safe for concurrent use: concurrent reads are fine, but if any goroutine writes while others read or write, the behavior is undefined and Go's runtime often panics with a 'concurrent map writes' fatal error.
Maps are reference types created with make or a literal, and the zero value is nil — you can read from a nil map but writing to it panics. Because the runtime does not lock maps, concurrent access must be synchronized by the programmer, typically with a sync.RWMutex around reads and writes, or by using sync.Map for high-contention, read-mostly workloads. Iteration order is deliberately randomized, so code must never depend on it.
- Fast average-case O(1) key lookup and insertion
- Simple, ergonomic literal and make syntax
- Comma-ok form distinguishes missing keys from zero values
- sync.RWMutex or sync.Map provides safe concurrent access when needed
- Randomized iteration order prevents accidental order dependence
AI Mentor Explanation
A map is like a dressing-room peg board where each player's name (key) hangs above their kit (value) — you find any kit instantly without scanning every peg. But if two managers rearrange pegs at the same moment while others are grabbing kit, chaos erupts and someone walks off with the wrong gear. Go behaves the same: unsynchronized simultaneous writes corrupt the board, so you post one manager with a whistle to gate access.
Step-by-Step Explanation
Step 1
Create the map
Use make(map[K]V) or a literal like map[string]int{"a": 1}; a nil map (var m map[K]V) reads fine but panics on write.
Step 2
Access with comma-ok
Use v, ok := m[key] to tell a missing key (ok == false) apart from a stored zero value.
Step 3
Know it is unsynchronized
The runtime does no locking; concurrent reads are safe, but any concurrent write with another read or write is a data race.
Step 4
Detect races
Run with go run -race; unsynchronized writes trigger a fatal 'concurrent map writes' error at runtime.
Step 5
Guard with a mutex
Wrap access in sync.RWMutex — RLock for reads, Lock for writes — to serialize mutations safely.
Step 6
Consider sync.Map
For read-mostly, high-contention caches with disjoint keys, sync.Map avoids explicit locking and can reduce contention.
What Interviewer Expects
- That a map is a hash table with average O(1) operations
- That maps are NOT safe for concurrent writes
- The comma-ok idiom for key presence
- That writing to a nil map panics
- Knowledge of sync.RWMutex and sync.Map for safe concurrency
Common Mistakes
- Claiming Go maps are goroutine-safe by default
- Writing to a nil map instead of initializing with make
- Relying on map iteration order being stable
- Confusing a missing key with a stored zero value
- Using sync.Map for write-heavy workloads where a mutex is better
Best Answer (HR Friendly)
“A Go map is a fast lookup table pairing keys with values. On its own it is not safe when several goroutines write to it at the same time, so you protect it with a lock or use a purpose-built concurrent map.”
Code Example
m := map[string]int{"apples": 3}
if v, ok := m["apples"]; ok {
fmt.Println(v) // 3
}
// Safe concurrent access
type Counter struct {
mu sync.RWMutex
m map[string]int
}
func (c *Counter) Inc(k string) {
c.mu.Lock()
c.m[k]++
c.mu.Unlock()
}
func (c *Counter) Get(k string) int {
c.mu.RLock()
defer c.mu.RUnlock()
return c.m[k]
}Follow-up Questions
- How does sync.Map differ from a map guarded by sync.RWMutex?
- Why is Go's map iteration order randomized?
- What happens when you write to a nil map?
- How does the -race detector help find map data races?
- When would you choose sharded maps over a single locked map?
MCQ Practice
1. Are Go maps safe for concurrent writes by default?
The Go runtime does not synchronize map access; concurrent writes (or a write alongside a read) are undefined and typically abort with 'concurrent map writes'.
2. What does v, ok := m[key] provide?
The comma-ok idiom returns the value and a boolean; ok is false when the key is absent, distinguishing it from a stored zero value.
3. What happens if you write to a nil map?
Reading a nil map yields zero values, but any write panics; you must initialize it with make or a literal first.
Flash Cards
What is a Go map? — A built-in hash table of unordered key-value pairs with average O(1) lookup, insert, and delete.
Are maps concurrency-safe? — No — concurrent reads are fine, but any concurrent write is a data race, often causing a fatal 'concurrent map writes' panic.
How do you check if a key exists? — Use the comma-ok form: v, ok := m[key]; ok is false when the key is absent.
What happens writing to a nil map? — It panics; initialize with make(map[K]V) or a literal before writing.
How to make map access safe? — Guard it with sync.RWMutex, or use sync.Map for read-mostly, high-contention cases.