Maps
A hash table with two behaviours that surprise most people once.
- Write code that tells a missing key from a zero value with
v, ok := m[k]. - Explain why ranging over a map may give a different order each time.
- Fix the panic caused by writing to a nil map.
What is a map in Go?
A map is a hash table: it stores values by key. Keys must be comparable with ==. Strings, numbers, pointers, and structs whose fields are all comparable work. Slices, maps and funcs do not.
m := map[string]int{"a": 1}m["b"] = 2v := m["missing"] // 0 — a missing key returns the ZERO VALUE, no errorv, ok := m["missing"] // v=0, ok=false — always use this two-value formdelete(m, "a")fmt.Println(len(m))for k, v := range m { // ORDER IS RANDOM, on purpose fmt.Println(k, v)}Three map rules worth memorising now
- Reading a missing key is not an error. It returns the zero value. Use
v, ok := m[k]whenever "absent" and "zero" mean different things. - Iteration order is randomised on purpose, so you cannot come to depend on it. To print a map in order, collect the keys into a slice, sort them, then range over the slice.
- Writing to a `nil` map panics. Reading from one is fine and gives zero values. A map field in a struct is
niluntil youmakeit.
Since Go 1.24, maps are built as Swiss tables, a newer hash-table design that makes lookups and inserts faster. Nothing you write changes: the syntax, the rules above and the random order all stay the same. Your old code just runs a bit quicker.
The modern stdlib helpers
Go 1.21 added the slices and maps packages to the standard library. Reach for these before writing a loop.
Preview: maps.Keys does not hand you a slice. It returns an iterator, something that gives you the keys one at a time. You will learn how they work in Iterators; for now, treat slices.Sorted(maps.Keys(m)) as "the keys, sorted".
s := []int{3, 1, 2}slices.Contains(s, 3) // trueslices.Sort(s) // s is now [1 2 3]slices.Index(s, 3) // 2slices.Reverse(s) // s is now [3 2 1]m := map[string]int{"b": 2, "a": 1}keys := slices.Sorted(maps.Keys(m)) // [a b] — preview, explained in Iterators- A missing key returns the zero value, not an error. Use
v, ok := m[k]. - Iteration order is randomised on purpose. Sort the keys when order matters.
- Writing to a
nilmap panics; reading from one is fine. - Maps are not safe for concurrent use. When the runtime detects a concurrent write, it crashes the program on purpose.
map[string]int, then print the top three. A map cannot be sorted, so you will have to move the pairs into a slice.WordCount(words []string) map[string]int that counts how many times each word appears. Example: WordCount([]string{"go", "is", "go"}) → map[go:2 is:1]. An empty list gives an empty map.Tab indents. Press Esc, then Tab, to leave the editor.
- 1Read a missing key and print the result. Then use the two-value form.
- 2Write to a map declared but never made, and read the panic.
- 3Range over the same map five times and watch the order change.