Go 泛型:限制映射键的类型?
来源:stackoverflow
时间:2024-03-24 17:54:49 189浏览 收藏
Go 1.18 中,通用链表无法作为映射键,因为其类型约束不符合可比较性要求。然而,Go 1.20 中引入了 comparable 约束,它适用于所有可比较类型,包括那些在运行时可能会出现混乱的类型。通过将列表定义为 comparable,它可以满足映射键的约束,从而允许在代码中使用通用链表作为映射键。
在下面的代码中,我定义了一个通用链表。 go1.18 很乐意使用列表的实例作为映射的键。但是,最后一行如果未注释,则无法编译;我收到错误:
cons[int] 没有实现可比较
是否有一个较弱的类型约束我可以使用来挑选出那些可以用作键的类型,或者这是有意的,还是一个编译器错误?
package main import "fmt" 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() {} func id[X comparable](x X) X { return x } func main() { x := Cons[int]{5, Nil[int]{}} m := map[List[int]]string{} m[x] = "Hi" // succeeds fmt.Println(m[x]) // prints "Hi" // fmt.Println(id(x)) // fails }
正确答案
go 1.20(2023 年 2 月)
comparable
是映射键的正确包罗万象的约束。
所有类型为 comparable as per the Go spec 的类型,即使比较可能在运行时发生混乱,也可以满足 comparable
约束。您的代码将在 1.20 中按预期进行编译。
这最终修复了以前的 go 版本中关于规范可比较类型与 comparable
类型的不一致问题。详情请参阅下文。
转到 1.18 和 1.19
预声明的 comparable
约束是映射键的正确约束,但是它只能通过严格可比较类型实例化,即支持 ==
和 !=
的类型(成为的条件)用作地图键)但在运行时不会出现恐慌。这不包括接口1。
这里提到了:https://go.dev/ref/spec#Type_constraints
预先声明的接口类型相当表示所有接口的集合 具有可比性的非接口类型。具体来说,t型 实现类似的 if:
t
不是接口类型,并且t
支持操作==
和!=
2t
是一个接口类型,t
类型集中的每个类型都实现comparable
即使可以比较不是类型参数的接口(可能导致运行时恐慌),它们也不会实现可比较。
这是一个重要的问题,因为基本接口类型通常支持 equality operators - 比较的是它们的动态类型/值。
因此,您的接口 list[x]
可以直接用作映射键,如 map[list[int]]string{}
中所示,但它没有实现 comparable
因为它有一个无限类型集(它没有术语,因此任何类型都可以实现它)。 cons
也没有实现它,因为它有一个 list[x]
类型的字段。对此没有“较弱”的约束。
考虑到嵌入 comparable
的约束对于映射键也有效,因此如果您确实需要在函数体中使用 islist()
方法,您可以定义这样的约束,并让您的列表为映射-key 结构实现该功能,而不是声明接口字段:
// may use this as a constraint type List interface { comparable isList() bool }
1:规范中的引用暗示存在实现 comparable
的接口类型,但实际上不可能使用任何接口实例化 comparable
:仅具有方法的接口具有无限类型集,并且具有类型的接口除了作为约束条件之外,术语不能在任何地方使用。
2:该规则实际上不涵盖支持 ==
的非接口类型,例如 type s struct { data any }
,但这些类型仍然无法实例化 comparable
https://go.dev/play/p/N-pmE0XC-hB。规范中的错误。
文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《Go 泛型:限制映射键的类型?》文章吧,也可关注golang学习网公众号了解相关技术文章。
-
502 收藏
-
502 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
139 收藏
-
204 收藏
-
325 收藏
-
477 收藏
-
486 收藏
-
439 收藏
-
357 收藏
-
352 收藏
-
101 收藏
-
440 收藏
-
212 收藏
-
143 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习