Go

Explain the cmp package: Compare, Less, Or. How do you do a multi-key sort, and how is NaN handled?

Question 138MediumGo 1.22 to 1.25

cmp (Go 1.21) provides Ordered, Compare(a, b) int (returns -1, 0 or +1) and Less(a, b) bool. Go 1.22 added Or(vals ...T) T, which returns the first non-zero argument and is ideal for chaining comparisons. For floats, Compare and Less treat NaN as less than any other value and equal to NaN. That gives a consistent total order, which the raw < operator does not, because NaN < x is always false.

type Person struct {
    Last, First string
    Age         int
}

people := []Person{{"Doe", "Jane", 30}, {"Doe", "Adam", 30}, {"Ali", "Zed", 25}}

slices.SortFunc(people, func(a, b Person) int {
    return cmp.Or(
        cmp.Compare(a.Last, b.Last),
        cmp.Compare(a.First, b.First),
        cmp.Compare(b.Age, a.Age), // descending age
    )
})
// [{Ali Zed 25} {Doe Adam 30} {Doe Jane 30}]

fs := []float64{3, math.NaN(), 1}
slices.Sort(fs)       // uses cmp.Less semantics
fmt.Println(fs)       // [NaN 1 3]

port := cmp.Or(os.Getenv("PORT"), "8080") // default value idiom

Also mention the built-in min/max (Go 1.21). If any argument is NaN, they return NaN. slices.SortStableFunc is needed when equal elements must keep their original order.

More on Generics

All 36 Generics questions