The maps Package
The maps Package
The maps package provides generic functions over maps—everything you used to write with a for range.
Mental model
maps provides generic functions over maps. maps.Keys returns a slice of keys in unspecified order. maps.Values returns values. maps.Clone makes a shallow copy. maps.Copy merges src into dst (overwrites on conflict). maps.Equal compares two maps element-by-element. maps.DeleteFunc removes entries where the function returns true. Import is "maps".
Worked examples
Case 1: maps.Clone
Clone a map[string]int price menu, mutate the clone, and show the original is unchanged.
// clone.go
package main
import (
"fmt"
"maps"
)
func main() {
menu := map[string]int{
"coffee": 250,
"tea": 200,
}
clone := maps.Clone(menu)
clone["coffee"] = 300
clone["pastry"] = 450
fmt.Printf("Original: %v\n", menu)
fmt.Printf("Clone: %v\n", clone)
}Run:
go run clone.goOutput:
Original: map[coffee:250 tea:200]
Clone: map[coffee:300 pastry:450 tea:200]
Case 2: maps.Keys and sorting
Get sorted keys for a seating chart using slices.Sort on the result for deterministic output.
// keys.go
package main
import (
"fmt"
"maps"
"slices"
)
func main() {
seats := map[string]string{
"T1": "Alice",
"T3": "Bob",
"T2": "Charlie",
}
// maps.Keys returns an iterator; slices.Sorted collects and sorts in one step
keys := slices.Sorted(maps.Keys(seats))
fmt.Printf("Sorted desks: %v\n", keys)
}Run:
go run keys.goOutput:
Sorted desks: [T1 T2 T3]
Case 3: maps.Copy
Merge two shift rosters map[string]string (name→window), showing a duplicate key is overwritten.
// copy.go
package main
import (
"fmt"
"maps"
)
func main() {
roster := map[string]string{
"Alice": "Morning",
"Bob": "Evening",
}
updates := map[string]string{
"Bob": "Night",
"Charlie": "Morning",
}
// src (updates) overwrites dst (roster)
maps.Copy(roster, updates)
fmt.Printf("Roster: %v\n", roster)
}Run:
go run copy.goOutput:
Roster: map[Alice:Morning Bob:Night Charlie:Morning]
Case 4: maps.Equal
Compare two ticket priority maps, true then mutate one and false.
// equal.go
package main
import (
"fmt"
"maps"
)
func main() {
t1 := map[string]int{
"T-100": 1,
"T-101": 2,
}
t2 := map[string]int{
"T-100": 1,
"T-101": 2,
}
fmt.Printf("Equal initially? %v\n", maps.Equal(t1, t2))
t2["T-102"] = 3
fmt.Printf("Equal after mutation? %v\n", maps.Equal(t1, t2))
}Run:
go run equal.goOutput:
Equal initially? true
Equal after mutation? false
Case 5: maps.DeleteFunc
Remove all menu items with price < 100 (cents).
// delete.go
package main
import (
"fmt"
"maps"
)
func main() {
menu := map[string]int{
"coffee": 250,
"tea": 200,
"water": 0,
"mint": 50,
}
maps.DeleteFunc(menu, func(k string, v int) bool {
return v < 100
})
fmt.Printf("Menu: %v\n", menu)
}Run:
go run delete.goOutput:
Menu: map[coffee:250 tea:200]
The trap
Trap 1: maps.Clone is a shallow clone
maps.Clone creates a copy of the map, but it copies values as-is. If the map stores pointers or references to structs (map[string]*Ticket), both maps point to the exact same underlying heap objects. Mutating a field through the clone mutates the original!
Save as shallow_trap.go:
// shallow_trap.go
package main
import (
"fmt"
"maps"
)
type Ticket struct {
ID int
Status string
}
func main() {
original := map[string]*Ticket{
"T-1": {ID: 101, Status: "open"},
}
clone := maps.Clone(original)
// Mutating the pointed-to object changes both maps:
clone["T-1"].Status = "closed"
fmt.Println("original:", original["T-1"].Status)
fmt.Println("clone: ", clone["T-1"].Status)
}Run:
go run shallow_trap.goOutput:
original: closed
clone: closed
If you need a deep clone of pointer values, allocate a new struct for each key explicitly.
Trap 2: Assuming map iteration order is stable
maps.Keys returns an iterator over keys in randomized hash order. If you assume keys will always iterate in insertion or sorted order, tests and serialization logic will behave flakily across runs and Go compiler versions. Always use slices.Sorted(maps.Keys(m)) if order matters.
The boring rule
- Use
maps.Clonefor simple value maps (map[string]int,map[string]string). For pointer values, clone structs explicitly. - Use
slices.Sorted(maps.Keys(m))to iterate keys deterministically. - Use
maps.Copy(dst, src)to merge maps instead of manual loops. - Use
maps.DeleteFuncfor in-place conditional eviction (pruning expired cache entries, clearing completed orders). - Use
maps.Equalfor direct map comparisons.
Try this
- In
keys.go, useslices.Sorted(maps.Values(seats))to get a sorted list of guest names. - In
shallow_trap.go, fix the aliasing by constructing a new&Ticket{ID: t.ID, Status: t.Status}inside a copy loop. Confirm the original remains"open". - In
delete.go, change the predicate to keep only items whose names start with"c".