Maps are Go's built-in hash table, used for lookups, counting, grouping and sets.
A map associates keys with values: map[string]int. Keys must be comparable with == — strings, numbers, booleans, pointers, channels, and arrays or structs made of those. Slices, maps and functions can't be keys.
Create maps with a literal, ages := map[string]int{"ann": 31}, or make(map[string]int). The zero value of a map is nil: reading from a nil map is fine (you get zero values), but writing to a nil map panics, so always initialise before inserting.
m[k] = vinserts or updates;delete(m, k)removes (no-op if absent);len(m)counts entries;clear(m)empties it.v := m[k]returns the zero value when the key is missing. To tell "missing" from "present with zero value", use the comma-ok form:v, ok := m[k].- Because missing keys read as zero, counting is just
counts[word]++.
Iterating with for k, v := range m visits entries in a deliberately randomised order. If you need a stable order, collect and sort the keys — in Go 1.23+, slices.Sorted(maps.Keys(m)) does it in one line.
Maps are reference-like: passing one to a function lets it modify the caller's map. They are not safe for concurrent writes; guard them with a mutex if several goroutines modify them. A map[string]struct{} (or map[string]bool) is the idiomatic set.
Example
package main
import (
"fmt"
"maps"
"slices"
"strings"
)
func main() {
counts := make(map[string]int)
for _, w := range strings.Fields("the cat saw the dog") {
counts[w]++
}
if n, ok := counts["the"]; ok {
fmt.Println("the:", n) // the: 2
}
_, ok := counts["bird"]
fmt.Println(ok) // false
for _, k := range slices.Sorted(maps.Keys(counts)) {
fmt.Print(k, "=", counts[k], " ") // cat=1 dog=1 saw=1 the=2
}
}Remember
v, ok := m[k]distinguishes missing from zero- Writing to a nil map panics — use
makeor a literal - Map iteration order is random; sort keys for stable output
Watch out for
- Writing tests or output that depend on map iteration order.