Key-value tables with the comma-ok idiom.
The maps Package
The companion to slices, added in Go 1.21.
It gives you generic helpers for the operations you used to write by hand: copy
a map, compare two maps, pull out keys or values.
Keys and Values (Go 1.23+: iterators)
In Go 1.23, maps.Keys and maps.Values return iterators that you walk with
range. To collect into a slice, wrap with slices.Collect:
Equal — deep map comparison
a := map[string]int{"x": 1, "y": 2}
b := map[string]int{"y": 2, "x": 1}
maps.Equal(a, b) // true — same keys, same values
Equal compares values with ==. For values that aren't comparable (like slices
inside a map), use maps.EqualFunc(a, b, func(v1, v2 T) bool { ... }).
Clone — independent copy
m := map[string]int{"a": 1}
n := maps.Clone(m)
n["a"] = 99
fmt.Println(m["a"]) // 1 — m is untouched
A plain assignment (n := m) would share the same underlying map; Clone is
the only stdlib way to get a one-level-deep independent copy. (Values are still
shallow — a map of slices still shares those slices.)
Copy and DeleteFunc
dst := map[string]int{"a": 1}
src := map[string]int{"b": 2, "c": 3}
maps.Copy(dst, src) // merges src into dst (overwriting on key collisions)
// Delete entries matching a predicate
maps.DeleteFunc(dst, func(k string, v int) bool {
return v == 0
})
maps.Copy is the modern way to merge — no for k, v := range src { dst[k] = v }.
What about len, delete, clear?
These stay built-in:
len(m) // number of entries
delete(m, k) // remove one key
clear(m) // since Go 1.21: remove every entry, retain capacity
clear is much faster than re-assigning m = map[K]V{} when you want to reuse
an existing map.