编程 Go 1.28 泛型集合提案 #80590:七个包、一套不导出的抽象接口

2026-09-16 21:02:08

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)」的抽象集合接口。

组件清单

提案把工作拆成了七个部分,各自有独立编号:

提案状态
#70471hash/maphash.Hasher已随 Go 1.27 发布
#69559container/hash.Map[K,V]提案中
#80584container/hash.Set[T]提案中
#69230container/set.Set[T]提案中
#77052container/mapset提案中
#60630container/tree.Map[K,V]提案中
#77397container/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/
复制全文 生成海报 Go 泛型 标准库 container

推荐文章

程序员茄子在线接单