Go Generic 'comparable'

2022-03-16

Go 1.18 was released today, and one of its major updates is Generics.

In Generics, there's a type named comparable. The official documentation explains it as follows:

The new predeclared identifier comparable is an interface that denotes the set of all types which can be compared using == or !=. It may only be used as (or embedded in) a type constraint.

✅ Comparable Types

  • Numeric types: bool, int, float, complex, string
  • Special types: interface, chan, Pointer
  • ⚠️ struct and array types are comparable only if all their members are of comparable types.
func isEqual(T comparable)(a T, b T) bool {
    return a == b
}

isEqual(1, 2) // true
isEqual("123", "123") // true
isEqual("123", "234") // false

type Person struct {
    Name string
}
isEqual(
    Person{Name: "foo"},
    Person{Name: "foo"},
) // true

❌ Non-Comparable Types

The following types are not comparable:

  • slice
  • map
  • func

⚠️ Exception

However, there is an exception for the error type. Although in Go it's common to compare error using == or !=:

if errors.New("err") == errors.New("err") {
    print("equal")
}
// output: equal

error is not considered comparable, so the following code will result in a compilation error:

isEqual(errors.New("err"), errors.New("err"))
// ❌ error does not implement comparable

Furthermore, even if a struct contains an error field, it will still result in an error.

type Person struct {
    Name string
    Error error // not comparable
}
isEqual(
    Person{Name: "foo"},
    Person{Name: "foo"},
)
// ❌ Person does not implement comparable

🎉  Thanks for reading and hope you enjoy it. Feel free to check out my other posts and find me on X and GitHub!