In Go 1.18 and earlier, the predeclared comparable constraint is required for types that are used as map keys. This constraint ensures that the type supports the == and != operators and does not panic when these operators are used.
However, this constraint is not always appropriate for types that can be used as map keys. For example, the following code defines a generic linked list:
type List[X any] interface { isList() } type Cons[X any] struct { Data X Next List[X] } func (Cons[X]) isList() {} type Nil[X any] struct{} func (Nil[X]) isList() {}
This code defines a List interface that is implemented by two types: Cons and Nil. The Cons type represents a non-empty list, while the Nil type represents an empty list.
The following code uses the List interface to create a map of lists to strings:
type List[X any] interface { isList() } func main() { x := Cons[int]{5, Nil[int]{}} m := map[List[int]]string{} m[x] = "Hi" // succeeds fmt.Println(m[x]) // prints "Hi" }
This code will compile and run successfully. However, if we try to use a method on the type Cons, we will get a compiler error:
type List[X any] interface { isList() } func main() { x := Cons[int]{5, Nil[int]{}} fmt.Println(id(x)) // error: Cons[int] does not implement comparable }
The error message indicates that the type Cons[int] does not implement the comparable constraint. This is because the Cons type has a field of type List[int], and the List[int] interface does not implement the comparable constraint.
One possible solution to this problem is to use a weaker type constraint. For example, we could use the following constraint:
type List[X any] interface { isList() Comparable() bool }
This constraint would allow us to use the Cons type as a map key, even though it does not implement the comparable constraint.
The comparable constraint is the correct catch-all constraint for map keys. All types that are comparable as per the Go spec, even if the comparison may panic at run time, can satisfy the comparable constraint. Your code will compile as expected in 1.20.
This finally fixes the inconsistency in previous Go version about spec-comparable types vs comparable types.
The above is the detailed content of Can Go Generics' `comparable` Constraint Be Relaxed for Map Keys?. For more information, please follow other related articles on the PHP Chinese website!