What happens if you add or delete map entries while ranging over the map?
m := map[int]bool{1: true, 2: true, 3: true}
for k := range m {
m[k+10] = true
}
fmt.Println(len(m)) // ?
for k := range m {
if k > 5 {
delete(m, k) // safe
}
}
The first len is nondeterministic. The spec says an entry added during iteration "may be produced during the iteration or may be skipped". New keys such as 11 may be visited, which then adds 21, and so on. You can see 6, 7, 8, or more on different runs.
Deleting during range is well defined: an entry removed before it is reached is not produced. Deleting the current key is fine, and the loop above is a correct filter.
Other gotchas: iteration order is deliberately randomized, so never depend on it (sort slices.Sorted(maps.Keys(m)) first). Writing to a map from several goroutines, or writing while another goroutine ranges over it, triggers fatal error: concurrent map iteration and map write. That is a fatal error, not a panic, so recover cannot catch it. If you need to add entries, build a separate map and merge it afterwards. The Swiss-table map implementation in Go 1.24 changed the internals but none of these rules. The spec semantics (random order, added entries may or may not appear, deleting is safe) are the same.
More on Tricky Output & Code-Review Puzzles
- Q490When is the receiver bound for a method value? What prints?
- Q491Code review: why does Counter always report 0, and what else is wrong?
- Q493Why won't m["a"].count++ compile, and what happens with a nil map?
- Q494Spot the bug: why is err nil after the if block?
- Q495Find the two WaitGroup bugs.
- Q496Why does this loop spin at 100% CPU after one channel closes?