Go

Which types are comparable in Go, and when does comparing values panic at run time?

Question 25HardGo 1.22 to 1.25

Comparable types (== and != work): booleans, numbers, strings, pointers, channels, interfaces, arrays of comparable elements, and structs whose fields are all comparable.

Not comparable: slices, maps and functions. They can only be compared to nil. Map keys must be comparable types.

Interfaces are the trap. An interface type is comparable at compile time, but comparing two interfaces whose dynamic types are the same and not comparable panics at run time.

var a, b any = []int{1}, []int{1}
fmt.Println(a == b) // panic: runtime error: comparing uncomparable type []int

var c, d any = []int{1}, "x"
fmt.Println(c == d) // false: dynamic types differ, so no panic

m := map[any]int{}
m[[]int{1}] = 1     // panic: runtime error: hash of unhashable type []int

type Key struct {
	Name string
	Tags []string
}
// _ = map[Key]int{}  // compile error: invalid map key type Key

Other rules:

  • Pointers are equal when they point to the same variable. Pointers to two distinct zero-size variables may or may not be equal.
  • Channels are equal when they come from the same make.
  • Function values can't be compared at all, not even through reflect (DeepEqual says they're equal only if both are nil).

Tools for types that aren't comparable: slices.Equal, maps.Equal, bytes.Equal, reflect.DeepEqual (slow), and github.com/google/go-cmp in tests.

More on Language Fundamentals & Types

All 39 Language Fundamentals & Types questions