Two objects are comparable in Go if their equality can be checked with == or != operations, which only happens if the equality is well-defined. For example, comparing two string values, pointers, or structs:
type S struct {
name string
}
func main() {
fmt.Println("a" == "b")
i := S{}
j := S{}
fmt.Println(i == j)
fmt.Println(&i == &j)
}
We can’t simply compare two maps, functions, or slices with the equality operations because there’s no clear, built-in meaning with them. For example, two slices can refer to different backing array, requiring deep recursive equality. The meaning of equality lies on how we structured those types.
func main() {
x := []string{}
y := []string{}
fmt.Println(x == y) // invalid operation: x == y (slice can only be compared to nil)compilerUndefinedOp
}
There are gotchas.
- Two arrays can be compared only if their types and lengths are the same and the types are comparable
- Two structs can be compared only if the struct doesn’t have properties that have non-comparable types
type S struct {
name string
}
type T struct {
name string
ages []int
}
func main() {
// array: can be compared because they have the same type and length
a := [1]string{"a"}
b := [1]string{"a"}
fmt.Println(a == b)
// array with different length can't be compmared
c := [2]string{"a", "a"}
fmt.Println(a == c) // invalid operation: a == c (mismatched types [1]string and [2]string)
// structs with properties having comparable types
i := S{}
j := S{}
fmt.Println(i == j)
// structs with properties having non-comparable types can't be compared
k := T{}
l := T{}
fmt.Println(k == l) // invalid operation: k == l (struct containing []int cannot be compared)
}