Go 1.28 泛型集合提案 #80590:七个包、一套不导出的抽象接口
Go Collections 工作组提出了伞形提案 Issue #80590,由 Jonathan Amsterdam、Alan Donovan、Robert Griesemer、Ian Lance Taylor 等 7 位核心贡献者发起。目标是在 Go 1.28 的标准库里落地哈希 Set/Map、树形有序 Map、新一代堆,以及一套用来解决「二元方法问题(binary method problem)」的抽象集合接口。
组件清单
提案把工作拆成了七个部分,各自有独立编号:
| 提案 | 包 | 状态 |
|---|---|---|
| #70471 | hash/maphash.Hasher | 已随 Go 1.27 发布 |
| #69559 | container/hash.Map[K,V] | 提案中 |
| #80584 | container/hash.Set[T] | 提案中 |
| #69230 | container/set.Set[T] | 提案中 |
| #77052 | container/mapset | 提案中 |
| #60630 | container/tree.Map[K,V] | 提案中 |
| #77397 | container/heap/v2.Heap | 提案中 |
其中 #70471 hash/maphash.Hasher 是基础件,定义自定义哈希函数与等价关系的标准接口,已经先一步随 Go 1.27 发布。
container/hash.Map[K,V]:基于哈希的通用 Map,键不要求可比较,切片、Map 这类类型也能作键。container/hash.Set[T]:基于哈希的通用 Set。container/set.Set[T]:面向可比较元素的规范 Set 类型。container/mapset:为「传统 Set」(即map[T]bool)提供集合运算的辅助函数包。container/tree.Map[K,V]:基于平衡二叉树的有序 Map。container/heap/v2.Heap:泛型二叉堆,替代难用的旧版container/heap。
为什么拖到 1.28:在等迭代器
Go 团队一直在等另一块拼图——迭代器(range-over iterators)。没有它,Set 没法直接用 for range 遍历,集合库的体验就不成立。Go 1.23 引入迭代器特性之后,补齐集合库的时机才算成熟,这也是这批提案被排到 1.28 的原因。
两个克制
不追求极致性能。 初版的目标是保证 API 正确和渐近复杂度(比如 O(log n)),不为微小常数级性能提升做过度设计。先求对,再求快。
暂不公开抽象接口。 集合类型里有个经典难题叫「二元方法问题」:两个不同实现的 Set 怎么比较、怎么求交并。工作组为此设计了一套基于 F-bounded 多态(用递归约束接口)的抽象接口 _AbstractCollection、_AbstractSet、_AbstractMap,并在 CL 761460 中加入了 container 包。但它们仅作为内部文档存在,不导出——避免过早锁死公共 API 契约,等实现跑一段时间再决定是否公开。
工程取舍
接口设计上严格区分两类操作:纯函数式集合代数返回新集合,原置修改版本则带 -With 后缀。这样既保住了表达式式的易用写法,也把内存分配效率的选择权留给调用方,不必为每一次集合运算都付一份新分配的代价。
未来还计划推出插入序 Map(insertion-ordered hash map)和 Stack。
对现有代码意味着什么
- 手写
map[T]struct{}的时代可以结束了; container/tree原生支持范围查询;container/hash允许切片、Map 等不可比较类型作键;container/mapset让那些不便重构的存量map[T]bool也能直接享受集合运算。
链接
- 伞形提案:https://github.com/golang/go/issues/80590
- 原文:https://tonybai.com/2026/07/29/go-1-28-generic-collections-proposal/