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
- Q136Write generic
Map,FilterandReducefor slices. Why aren't they in the standard library'sslicespackage? - Q137What is
golang.org/x/exp/constraints, how does it relate tocmp.Ordered, and how do you define your own numeric constraint? - Q139Which generic helpers in
slicesandmapsshould a senior Go developer know, and what are their gotchas? - Q140How do generics combine with Go 1.23 iterators (
iter.Seq)? Write lazyFilterandMapadapters and explain theyieldcontract. - Q141What is
iter.Pull, and when do you need it? Implement a genericZip. - Q142What are generic type aliases (Go 1.24), and how do they differ from generic type definitions?