Maps
A map in Go is a hash table — map[K]V. Lookup, insert, delete are O(1) average. Iteration order is randomised on purpose — do not rely on it.
Create, read, write, delete, idioms
EXAMPLE
package main
import (
"fmt"
"sort"
)
func main() {
// 1) Create
m := map[string]int{} // empty
n := map[string]int{"a": 1, "b": 2} // literal
p := make(map[string]int, 100) // hinted capacity
// 2) Write
m["score"] = 42
// 3) Read — zero value if missing!
v := m["missing"] // 0 — silent surprise
// Two-value read tells you if it's there
if v, ok := m["score"]; ok {
fmt.Println("found:", v)
}
// 4) Delete
delete(m, "score")
// delete on a missing key is a no-op (no panic)
// 5) Length
fmt.Println(len(n))
// 6) Iterate — order is RANDOMISED
for k, v := range n {
fmt.Println(k, v)
}
// 7) Sort keys for deterministic iteration
keys := make([]string, 0, len(n))
for k := range n {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
fmt.Println(k, n[k])
}
// 8) Maps of slices — count-by
wordCount := map[string]int{}
for _, w := range []string{"go", "go", "rust", "go"} {
wordCount[w]++
}
// map[go:3 rust:1]
// 9) Set — use map[T]struct{}
seen := map[string]struct{}{}
seen["alice"] = struct{}{}
seen["bob"] = struct{}{}
if _, ok := seen["alice"]; ok { /* ... */ }
// 10) Nested maps — "group by"
byCity := map[string][]User{}
for _, u := range users {
byCity[u.City] = append(byCity[u.City], u)
}
// 11) Map values are NOT addressable
type Point struct{ X, Y int }
pts := map[string]Point{"a": {1, 2}}
// pts["a"].X = 9 // ERROR — cannot assign to struct field of map value
pt := pts["a"]
pt.X = 9
pts["a"] = pt
// Or use pointers if frequent updates:
pp := map[string]*Point{"a": {1, 2}}
pp["a"].X = 9 // OK
// 12) Concurrent maps — built-in map is NOT goroutine-safe
// Use sync.RWMutex or sync.Map
var mu sync.RWMutex
counts := map[string]int{}
go func() {
mu.Lock()
counts["a"]++
mu.Unlock()
}()
// sync.Map — for write-once, read-many workloads only
var sm sync.Map
sm.Store("a", 1)
if v, ok := sm.Load("a"); ok { fmt.Println(v) }
// 13) Initialise OR die
var bad map[string]int // nil map
// bad["x"] = 1 // panic: assignment to entry in nil map
bad = map[string]int{}
bad["x"] = 1
}
Why it matters
Always use the two-value read for keys that may be absent — v, ok := m[k]. The single-value read returns the zero value, which silently hides “not found” bugs.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
ages := map[string]int{"Ada": 36}
ages["Bo"] = 28
if v, ok := ages["Ada"]; ok {
fmt.Println(v)
}
delete(ages, "Bo")
Try it Yourself »
Exercise
Make an empty map of string to int.
m :=
(map[string]int)
Four letters.
Discussion
Loading…