Is it safe to add or delete map entries while ranging over the map?
Question 58MediumGo 1.22 to 1.25
Yes, within one goroutine. The spec defines the behaviour:
- Deleting an entry that has not been reached yet means it will not be produced. Deleting the current key is always safe. This is the idiomatic way to filter a map in place.
- Adding an entry during iteration means it may or may not be produced. The result can differ between runs.
m := map[int]bool{1: true, 2: false, 3: true, 4: false}
// Safe in-place filter
for k, v := range m {
if !v {
delete(m, k)
}
}
fmt.Println(len(m)) // 2
// Library form (Go 1.21)
maps.DeleteFunc(m, func(k int, v bool) bool { return k > 2 })
// Nondeterministic: new keys may be visited
n := map[int]int{0: 0}
count := 0
for k := range n {
if count++; count > 100 {
break
}
n[k+1] = k + 1
}
fmt.Println(count) // varies between runs
Interviewer angle: contrast this with Java's ConcurrentModificationException. Go does not fail fast here. Across goroutines, though, any write during a range is a data race, and the runtime may kill the process ("concurrent map iteration and map write").
More on Arrays, Slices, Maps & Strings
- Q56What changed in Go 1.24 with Swiss Tables? Why are they faster?
- Q57Why is map iteration order random, and how do you iterate deterministically?
- Q59What happens when multiple goroutines access a map concurrently? How do you make it safe?
- Q60When should you use sync.Map instead of a map with a mutex?
- Q61Why does m["k"].Field = 1 fail to compile for map[string]T where T is a struct?
- Q62Why can't you take the address of a map element (&m[k]), when you can with slice elements?