Describe how Go maps were implemented before Go 1.24 (buckets, tophash, load factor, growth).
Question 55HardGo 1.22 to 1.25
The classic runtime map (runtime.hmap) is a hash table with 2^B buckets:
- Each bucket (
bmap) holds 8 entries. It starts withtophash [8]uint8, the top 8 bits of each key's hash, used as a quick filter. Then come 8 keys packed together, then 8 values packed together. Packing keys and values separately avoids padding (for examplemap[int64]int8). Finally there is anoverflowpointer to chained buckets. - The low B bits of the hash pick the bucket, and the high 8 bits are compared in
tophashbefore any full key comparison. - Each map gets a random hash seed, which defends against hash-flooding DoS attacks.
- Keys or values larger than 128 bytes are stored indirectly, as pointers.
Growth happens when the average load exceeds 6.5 entries per bucket, or when there are too many overflow buckets. The first case doubles the table. The second causes a "same-size grow" that compacts chains after many deletes. Growth is incremental: oldbuckets are kept and evacuated a bucket or two at a time on each later write or delete. This spreads out the cost, so no single insert pauses for O(n).
// Pre-size to avoid repeated growth + evacuation work
m := make(map[string]int, 10_000)
Consequences interviewers probe:
- Elements move during growth, so
&m[k]is forbidden. - Iteration must work across old and new buckets, so the order is unspecified.
- Maps never shrink.
- A map value is a
*hmap, so maps act like references when passed to functions.
More on Arrays, Slices, Maps & Strings
- Q53Why do the slices package functions use the constraint [S ~[]E, E any] instead of just []E?
- Q54Which slices and maps package functions do you use daily, and how do they work with iterators (Go 1.23)?
- 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?
- Q58Is it safe to add or delete map entries while ranging over the map?
- Q59What happens when multiple goroutines access a map concurrently? How do you make it safe?