Learn Go← Dashboard

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:

go playground
Loading...

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.

You write `n := m; n["x"] = 1`. What happens to `m`?