Go 泛型:映射键的类型约束
问题:
为什么以下内容使用通用链表作为映射时代码无法编译key?
type List[X any] interface { isList() } type Cons[X any] struct { Data X Next List[X] } func (Cons[X]) isList() {} func main() { x := Cons[int]{5, Nil[int]{}} m := map[List[int]]string{} m[x] = "Hi" fmt.Println(m[x]) fmt.Println(id(x)) }
答案:
在 Go 1.18 和 1.19 中,映射键需要预先声明的可比较约束,并且它将使用限制为严格可比较的类型支持 == 和 != 比较,而不会在运行时出现恐慌。接口即使支持相等比较,也不会实现可比较,因为它们具有无限类型集。
虽然 List[X] 接口本身可以用作映射键,但 Cons[X] 结构可以未实现可比较,因为它包含 List[X] 字段。没有更弱的约束可用于识别适合用作映射键的类型。
但是,在 Go 1.20(2023 年 2 月)中,此行为已得到修复。可比较现在接受根据语言规范可比较的所有类型,即使它们可能因比较而在运行时出现恐慌。这使得代码能够成功编译。
替代约束:
如果需要使用包含 isList() 方法的约束,您可以定义自己的约束约束如下:
type List interface { comparable isList() bool }
然后,让您的地图键结构实现此 List 接口,而不是声明接口田野。
以上是为什么通用链表不能用作 Go 中的 Map Key(1.20 之前)?的详细内容。更多信息请关注PHP中文网其他相关文章!