Generic Algorithms: slices, maps & cmp Packages
Go 1.21 added slices, maps, and cmp - generic-first stdlib packages for sorting, searching, cloning, and three-way comparison.
Search across all documentation pages
Go 1.21 added slices, maps, and cmp - generic-first stdlib packages for sorting, searching, cloning, and three-way comparison.
Use them before custom helpers; extend with your own generics only for domain logic they do not cover.
slices operates on []E with constraints like cmp.Ordered or comparable.
maps provides copy, delete, and equality for map[K]V.
cmp defines Ordered, Compare, and Or for building constraints and comparers.
Custom algorithms follow the same patterns: one type parameter for elements, separate parameters for keys and values when needed.
Quick-reference recipe card - copy-paste ready.
import (
"cmp"
"slices"
)
func TopN[T cmp.Ordered](data []T, n int) []T {
if n <= 0 {
return nil
}
cp := slices.Clone(data)
slices.Sort(cp)
if n > len(cp) {
n = len(cp)
}
return cp[len(cp)-n:]
}When to reach for this:
cmp.Ordered instead of copying large unions.package main
import (
"cmp"
"fmt"
"maps"
"slices"
)
type User struct {
Name string
Age int
}
func main() {
nums := []int{3, 1, 4, 1, 5}
slices.Sort(nums)
fmt.Println(nums)
fmt.Println(slices.BinarySearch(nums, 4))
m1 := map[string]int{"a": 1, "b": 2}
m2 := maps.Clone(m1)
m2["c"] = 3
fmt.Println(maps.Equal(m1, m2))
users := []User{{"ann", 30}, {"bob", 25}}
slices.SortFunc(users, func(a, b User) int {
return cmp.Compare(a.Age, b.Age)
})
fmt.Println(users)
}What this demonstrates:
slices.Sort requires ordered elements; SortFunc accepts custom comparers returning cmp sign.maps.Clone and maps.Equal avoid hand-rolled copy/equality.cmp.Compare on fields, not == on structs unless fully comparable and that is the intended order.slices functions mutate slices in place unless the name says Clone or returns a new slice.maps functions do not deep-copy values; pointers and slices inside values alias like ordinary map assignment.cmp.Compare returns -1, 0, or 1 for ordered types and is the preferred comparer return type for slices.SortFunc.| Function | Purpose |
|---|---|
Sort, SortFunc | In-place sort |
BinarySearch, BinarySearchFunc | Search sorted slice |
Contains, Index | Linear search |
Clone, Compact, Delete | Slice memory operations |
Insert, Replace | Structural edits |
| Function | Purpose |
|---|---|
Clone | Shallow copy of map |
Copy | Merge into destination |
Equal | Deep equality of keys and values |
DeleteFunc | Remove by predicate |
| Symbol | Purpose |
|---|---|
cmp.Ordered | Constraint for ordered built-ins and underlying types |
cmp.Compare(x, y) | Three-way compare for ordered types |
cmp.Or(x, y, …) | Pick first non-zero compare result in sort keys |
// Multi-key sort with cmp.Or
slices.SortFunc(records, func(a, b Record) int {
return cmp.Or(
cmp.Compare(a.Region, b.Region),
cmp.Compare(a.Name, b.Name),
)
})slices.SortFunc over sort.Slice for new code - clearer comparer signatures.slices.SortStableFunc fits your Go version and use it when equal elements must keep input order.Map transforms are still useful: func Map[T, U any](in []T, f func(T) U) []U.== on structs - Use SortFunc with explicit field order. Fix: cmp.Or on fields.maps.Clone deep-copies - Values alias. Fix: clone nested structures explicitly when needed.cmp.Ordered.maps.Copy - Panic on write to nil map. Fix: dst = make(map[K]V) before copy.| Alternative | Use When | Don't Use When |
|---|---|---|
sort package | Legacy code, non-slice types | New slice-only code |
| Hand-written loops | Tiny one-off in hot path already inlined | Repeated algorithm across types |
x/exp/slices experiments | Bleeding-edge features | Production without vetting |
| Domain-specific tree/index | Order statistics beyond slice sort | Simple in-memory batches |
Always for production maintenance - stdlib tracks Go releases and optimizations.
Custom generics for one-liners rarely pay off.
Sort needs cmp.Ordered elements.
SortFunc accepts any element type with a comparer function.
Yes - new backing array.
Use when you must detach from caller memory.
Two nil maps are equal.
Nil vs empty non-nil map are not equal.
Returns the first non-zero comparison in a chain.
Ideal for lexicographic multi-field sorts.
byte is ordered.
Sort works; remember bytes package also has specialized helpers.
Support varies by version and board.
Verify in CI for embedded targets.
Simple Map with []T to []U is a few lines.
Filter returns clipped slice or append to preallocated buffer.
It finds any matching index in sorted data.
Walk neighbors if you need all equal elements.
Yes for header lists, allowed methods, and path segment sorting in tests.
Keep handler signatures non-generic.
Small monomorphized bodies often inline like hand-written code.
Benchmark if doubtful.
slices.SortFunc with cmp.Compare or cmp.Or comparers.
slices.Contains introcmp.Ordered definitionmaps.Equal vs ==Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 18, 2026