Min Max and Clear Builtins Arrived in Go 1.21 Explained
The min and max builtins compare any ordered values and clear empties a map or zeroes a slice. See clamping, the NaN case and the go.mod version rule.

Three small additions to the language in Go 1.21 removed some of the most repeated helper functions in Go code. Every project had its own minInt and maxInt, and every project had the loop that deletes every key from a map. They are now builtins, and they have a few details worth knowing before you delete your helpers. This tip is part of the Go basics path, and the full list of builtins is in the builtin functions reference.
Tested with Go 1.25.6, macOS on Apple Silicon (arm64)
min and max
Both take one or more arguments of an ordered type, numbers or strings, and return the smallest or largest. They are evaluated in place and work with constants, as the output below shows:
package main
import (
"fmt"
"math"
)
func clamp(x, lo, hi int) int {
return min(max(x, lo), hi)
}
func main() {
fmt.Println(min(3, 1, 2), max(4, 9), min("pear", "apple"), max(2.5, 1))
fmt.Println(clamp(15, 0, 10), clamp(-5, 0, 10), clamp(7, 0, 10))
var a int32 = 5
fmt.Println(max(a, 10), min(1.5, 2))
fmt.Println(min(1, math.NaN()), max(0, math.Inf(1)))
}1 9 apple 2.5
10 0 7
10 1.5
NaN +InfThe first line mixes types in a way that works: every argument in each call has one ordered kind, and the untyped constants in max(2.5, 1) adapt to float64. clamp is the idiom I write most often: take the larger of the value and the lower bound, then the smaller of that and the upper bound. In the third line max(a, 10) returns an int32, because the constant 10 took the type of a. The two arguments must be the same typed kind otherwise, so max(int32(1), int64(2)) is a compile error.
The last line is the float edge: min(1, NaN) is NaN, because any comparison with NaN is unordered and the builtins propagate it. That matches IEEE 754 and it is easy to forget when you clamp user-supplied floats. If a NaN can reach the clamp, check math.IsNaN first, as the floating point article discusses. The standard math.Min and math.Max have the same NaN behavior and work only on float64, so the builtins are the better choice for new code. For a slice, slices.Min and slices.Max find the extreme element, and they panic on an empty slice.
clear
clear has two meanings, depending on what you give it:
package main
import "fmt"
func main() {
m := map[string]int{"a": 1, "b": 2}
clear(m)
fmt.Println(len(m), m == nil)
m["c"] = 3
s := []int{1, 2, 3}
t := s[:2]
clear(t)
fmt.Println(s, len(t))
}0 false
[0 0 3] 2On a map it deletes every entry and leaves a usable empty map, which the program shows by adding a key afterwards. This replaces the loop for k := range m { delete(m, k) } and the allocation of m = make(map[string]int), and unlike the latter, other references to the same map see it emptied. On a slice it sets every element to its zero value and does not change the length. Clearing the subslice t zeroed the first two elements of the shared array s, which the output shows as [0 0 3], and len(t) is still 2. To also shrink, reslice afterwards, s = s[:0]. Zeroing elements matters for slices of pointers, because it lets the garbage collector free what they pointed to, as removing an element without leaking it explains.
One thing clear on a map does not do is release memory, since the table keeps its capacity, as the maps guide measured. For a map that spiked and should shrink, build a new one.
The version rule
These builtins need the language version in go.mod to be 1.21 or later. A module that declares an earlier version gets an error naming the requirement, even if the toolchain is newer:
package main
import "fmt"
func main() {
fmt.Println(min(1, 2))
}# example.test/lab
./main.go:6:14: built-in min requires go1.21 or later (-lang was set to go1.20; check go.mod)The message says built-in min requires go1.21 or later, with a note that the language version was set to 1.20 and a hint to check go.mod. The same applies to max and clear. If you maintain a library for users on older Go versions, keep your helper functions and leave the go line low. For an application, raise the line to the version you build with, and delete the helpers. The release notes list the additions under Go 1.21, and the semantics are in the specification on min and max.


