Go

What is comparable? What changed in Go 1.20, and what does this program print?

Question 117HardGo 1.22 to 1.25

comparable is a predeclared constraint for types that support == and !=. It covers booleans, numbers, strings, pointers, channels, arrays and structs of comparable types, and interfaces. It excludes slices, maps and functions. You need it for map keys: func Keys[K comparable, V any](m map[K]V).

Before 1.20, interface types such as any did not satisfy comparable, because comparing two interface values can panic at run time. Go 1.20 relaxed this: spec-comparable types, including interfaces and structs containing interfaces, now satisfy comparable, even though they are not strictly comparable.

func Eq[T comparable](a, b T) bool { return a == b }

func main() {
    fmt.Println(Eq[any](1, 1))  // true
    fmt.Println(Eq[any](1, "1")) // false (different dynamic types)
    var x, y any = []int{1}, []int{1}
    fmt.Println(Eq(x, y))        // panics
}

Output: true, false, then panic: runtime error: comparing uncomparable type []int. The call compiles because T = any satisfies comparable since Go 1.20.

Other gotchas: comparable cannot appear in a union, and it does not give you ordering (<). Use cmp.Ordered for that.

More on Generics

All 36 Generics questions