New min and max built-in functions in Go 1.21

The Go programming language is constantly evolving, regularly introducing new exciting features that boost development efficiency and improve code maintainability. The latest release Go 1.21 brings many exciting things, from profile-guided optimization to standard library packages for structured logging, slices and maps operations (see the full release notes for more details). But in this post I want to describe two new built functions that caught my eye: min and max.

These functions are designed to provide concise and straightforward ways to compute the smallest and largest values from ordered types. Both functions accept values of an ordered type: integers, floats, or strings (or their derived types) and at least one argument should be specified.

minValue := min(4, 8, 1) // min, integers
fmt.Println(minValue)    // 1

maxValue := max(4, 8, 1) // max, integers
fmt.Println(maxValue)    //8

minFloat := min(1.23, 0.99, 16.78) // min, floats
fmt.Println(minFloat)              // 0.99

minX := min(1.23, 2, 99, 0.5) // integers and floats
fmt.Println(minX)             // 0.5, float

maxString := max("b", "abc", "x", "pq", "qp") // max, strings
fmt.Println(maxString)                        // "x"

type MyInt int
a := MyInt(6)
b := MyInt(78)
c := max(a, b)
fmt.Println(c) // 78

For floating-point arguments negative zero, NaN, and infinity the following rules apply:

xymin(x, y)max(x, y)Notes
-0.00.0-0.00.0negative zero is smaller than (non-negative) zero
-Infy-Infynegative infinity is smaller than any other number
+Infyy+Infpositive infinity is larger than any other number
NaNyNaNNaNif any argument is a NaN, the result is a NaN

Please, keep in mind, that these functions do not work with slices. To work with slices, use slices package instead as shown below:

input := []int{1, 2, 3}

// Do not work with slices. The following won't compile.
// m := min(input) // invalid argument: input (variable of type []int) cannot be ordered

// To work with slices, use slices package.
m := slices.Min(input)
fmt.Println(m) // 1

Also, I would like to mention that these functions won’t break the existing code that already uses the names min and max. Builtins aren’t keywords and you can shadow them:

max := "This is Max"
min := 8 - 3
fmt.Println(max, min) // This is Max 5