Go Generic 'comparable'

2022-03-16

Go 1.18 今天推出了,其中一個最大的更新莫過於是 Generics

在 Generics 中有個名為 comparable 的 type,在官方更新文件中對它的解釋是這樣的:

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.

✅ 可比較類型

  • 數值類型 bool, int, float, complex, string
  • 特殊類型 interface, chan, Pointer
  • ⚠️ structarray 需要所有 member 都是 comparable 類型,才可以 comparable
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

❌ 無法比較類型

以下類型都不是 comparable 的:

  • slice
  • map
  • func

⚠️ 例外

但是其中有一個例外是 error 類型,雖然在 Go 裡面平常是可以用 ==!= 來比較 error

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

但是 error 不屬於 comparable,因此如果這樣寫的話將會編譯錯誤。

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

另外,就算在 struct 之中含有 error 的 field,也一樣會有錯誤。

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

🎉  感謝您的閱讀,不仿看看我的其他文章,也歡迎在 XGitHub 上交流。