Go

Why can't you compare slices with ==? How do you check equality of slices, maps, and structs containing them?

Question 51MediumGo 1.22 to 1.25

Slices, maps, and functions are not comparable. You can compare them only to nil. The language designers left out == for slices on purpose, because it is ambiguous: shallow (same backing array) or deep (same elements)? The deep version would also need to handle cycles and could be expensive without anyone noticing. So any struct with a slice field is also not comparable and cannot be a map key.

a := []int{1, 2, 3}
b := []int{1, 2, 3}
// fmt.Println(a == b) // compile error: slice can only be compared to nil

fmt.Println(slices.Equal(a, b))           // true
fmt.Println(bytes.Equal([]byte("x"), nil)) // false; bytes.Equal(nil, []byte{}) is true

m1 := map[string]int{"a": 1}
m2 := map[string]int{"a": 1}
fmt.Println(maps.Equal(m1, m2))           // true

type T struct{ Tags []string }
// map[T]int{} // compile error: invalid map key type T

// Generic custom equality
eq := slices.EqualFunc(a, b, func(x, y int) bool { return x == y })
_ = eq

Gotchas:

  • reflect.DeepEqual is slow and treats nil and empty as different.
  • Comparing interface values that hold slices compiles, but panics at run time: any([]int{}) == any([]int{}) fails with "comparing uncomparable type []int".
  • In tests, prefer github.com/google/go-cmp/cmp.Diff for readable output.

More on Arrays, Slices, Maps & Strings

All 37 Arrays, Slices, Maps & Strings questions