Min and max

September 17, 2024

I always try to add my own commentary, examples, or other explanation in these emails.

Today I’m not really sure what to add.

min and max are such basic, and self-evident features, that the biggest surprise about these is that they’re such recent additions to the language. They were added just barely a year ago, with Go 1.21.

I will add a bit after we read about min and max, though.

Min and max

The built-in functions min and max compute the smallest—or largest, respectively—value of a fixed number of arguments of ordered types. There must be at least one argument [Go 1.21].

The same type rules as for operators apply: for ordered arguments x and y, min(x, y) is valid if x + y is valid, and the type of min(x, y) is the type of x + y (and similarly for max). If all arguments are constant, the result is constant.

var x, y int
m := min(x)                 // m == x
m := min(x, y)              // m is the smaller of x and y
m := max(x, y, 10)          // m is the larger of x and y but at least 10
c := max(1, 2.0, 10)        // c == 10.0 (floating-point kind)
f := max(0, float32(x))     // type of f is float32
var s []string
_ = min(s...)               // invalid: slice arguments are not permitted
t := max("", "foo", "bar")  // t == "foo" (string kind)

For numeric arguments, assuming all NaNs are equal, min and max are commutative and associative:

min(x, y)    == min(y, x)
min(x, y, z) == min(min(x, y), z) == min(x, min(y, z))

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

   x        y    min(x, y)    max(x, y)

  -0.0    0.0         -0.0          0.0    // negative zero is smaller than (non-negative) zero
  -Inf      y         -Inf            y    // negative infinity is smaller than any other number
  +Inf      y            y         +Inf    // positive infinity is larger than any other number
   NaN      y          NaN          NaN    // if any argument is a NaN, the result is a NaN

For string arguments the result for min is the first argument with the smallest (or for max, largest) value, compared lexically byte-wise:

min(x, y)    == if x <= y then x else y
min(x, y, z) == min(min(x, y), z)

There’s one other function I’d like to call your attention to, that has some similiarities. It’s not part of the spec, but was added to the standard library at the same time, and that is cmp.Or. cmp.Or works like min and max, in that it takes one or more arguments of the same type, but rather than returning the minimum or maximum, it returns the first of the arguments to not equal the type’s zero value.

a := min(0, 3, 4, 1) // 0
b := max(0, 3, 4, 1) // 4
c := cmp.Or(0, 3, 4, 1) // 3

Quotes from The Go Programming Language Specification Language version go1.23 (June 13, 2024)


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Get daily content like this in your inbox!

Subscribe