文章摘要
Go集合工作组于2025年底成立,旨在为标准库引入通用集合类型。该提案概述了为Go 1.28设计的新集合API,包括堆、集合等数据结构,并提供了相关具体提案和实现的链接。
文章总结
标题:提议:container/...:通用集合类型
背景: Go 集合工作组于2025年底成立,旨在遵循Go实用与简洁的原则,将常见集合数据结构引入标准库。成员包括Jonathan Amsterdam、Alan Donovan、Robert Griesemer、Daniel Martí、Roger Peppe、Keith Randall和Ian Lance Taylor。目前,工作组已准备好与社区分享成果。
本议题是讨论Go 1.28新集合API相关提议的总纲,概述核心主题并链接具体提议及实现。
Go标准库目前提供的集合类型较少,主要依赖内置的切片和映射类型。其中最重要的集合是堆(用于优先队列),但集合(Set)类型缺失,通常用map[T]bool或map[T]struct{}替代。基于二叉树的顺序映射和集合则完全缺失。
自Go 1.18引入泛型、Go 1.23引入迭代器后,库定义类型已能实现与内置类型相当的用户体验,且切片和映射的常见操作可通过库函数表达。本工作旨在为标准库添加若干重要数据类型,并建立其API及未来扩展的规范。
提议内容: 新增内容包括:
- hash/maphash.Hasher:为自定义哈希函数和等价关系提供标准接口,适用于键类型不可比较(如切片或映射)或默认比较结果错误的情况。
- container/hash.Map[K,V]:基于哈希的映射,使用上述自定义哈希函数。
- container/hash.Set[T]:基于哈希的集合。
- container/set.Set[T]:元素可比较的规范集合类型,透明表示为
map[T]struct{},支持并集、交集等操作,比传统map[T]bool更便捷。 - container/mapset:辅助函数包,用于操作无法更改API的现有代码中的传统集合。
- container/ordered.Map[K,V]:有序映射,当前实现基于平衡二叉树,但设计不限于此。
- container/heap/v2.Heap:通用二叉堆API,替代现有难用的堆实现。
后续还将考虑其他提议,如插入有序哈希映射和栈。
所有数据结构的初始实现力求简单满足API和渐进性能预期,后续优化(如降低常数因子)不在提议范围内。
新包将位于现有container目录下,但为避免与Linux容器概念混淆,我们更倾向使用“集合”一词。
抽象集合约束接口: 新Map和Set类型的大多数方法不限于具体表示类型,但存在“二元方法问题”,需使用F-有界多态或递归约束接口。container包中已添加未导出的抽象集合、集合和映射约束接口类型,用于编写跨具体集合类型的抽象辅助函数。这些接口目前不公开,但有助于确保一致性。未来可能根据经验决定是否发布规范约束类型。
其他设计选择:
- 方法尽可能返回更多信息,避免重复查找。例如,变异方法报告集合大小是否变化;
Map.Set和Map.Delete返回前一个键及布尔值。 Map.Set应替换相同键的现有条目,遵循内置映射行为。- 集合无
Equal方法,因为映射值可能不可比较。 - 基本集合操作(如
Intersects、Union)作为接口的一部分,以支持高效实现,尽管部分操作可抽象表达。 - 次要操作(如
Take、Arbitrary)从接口中移除,改为使用抽象集合接口的泛型操作。 - 集合代数操作(如
Union)提供纯函数式和变异式两种变体,分别注重便利性和分配效率。 - 可定义
KeySetView包装类型,使映射的键集满足集合抽象。 - 部分操作与现有
maps包功能平行,未来可能提议添加maps.Contains、maps.ContainsAll和maps.DeleteAll。
评论总结
根据评论内容,主要观点和论据如下:
1. 对泛型加入的积极评价
- 评论认为泛型是“迟来总比没有好”,能解决集合、类型堆等长期缺失的功能(评论3)。
- 关键引用:
- "Well, better late than never. Stuff like sets or a typed heap is long overdue."(评论3)
- "Well, finally! I wish they wouldn’t mix mutation methods in there, but ok."(评论5)
2. 对泛型设计及Go语言方向的批评
- 部分评论认为泛型与Go语言现有设计不匹配,甚至“让普通代码更难写”(评论6)。
- 关键引用:
- "Generics was the worst thing ever added to the language. We're making it easier for library builders and harder for ordinary code to be written."(评论6)
- "On one hand I'm glad to see this being added, but its becoming obvious building generics into the language as-is just isn't a good fit."(评论2)
3. 对Go团队决策过程的质疑
- 评论指出Go团队曾坚决反对泛型,多年后却改变立场,浪费了开发者时间(评论8)。
- 关键引用:
- "First they said they won't add generics. They violently defended that decision... Now the Golang team adds them. Why waste so much developer time?"(评论8)
- "Step by step, Go is now learning the hard lessons every other language has learned over the last 20 years."(评论9)
4. 其他观点
- 有评论将Go的问题归咎于“某家公司”(评论7),或调侃“期待G2EE作为规范发布”(评论4)。
- 关键引用:
- "Golang's biggest problem is a certain company."(评论7)
- "Looking forward to see G2EE being released as a specification /s"(评论4)
总结:评论对Go泛型的加入呈现两极分化——支持者认为填补了长期空白,反对者批评其设计不协调且决策反复。部分评论还质疑Go团队的历史立场和开发效率。