大家好,我是煎鱼。
之前 Go 核心团队乘机推广了标准库 v2 的更新计划,想着把一些老旧的标准库给干掉。在上一步已经把 math/rand/v2
给做了,官方也认为非常成功。
后续将开始计划新标准库 sync/v2
的更新和发布。今天文章主要分享此提案。
#go/issues/71076
起源
本次新标准库 sync/v2
的一个改造重点,来自于一个一揽子提案《spec: add generic programming using type parameters[1]》:
图片
核心目的就是:“建议在 Go 语言中添加对类型参数的支持。这将改变 Go 语言,使其支持一种通用编程形式。”
简单来讲,就是用逐步用泛型重构一切适用的标准库。
新提案:sync/v2
背景
当前 sync
包提供了 Map
和 Pool
类型。这些类型是在 Go 支持泛型之前设计的,其操作的值类型均为 any
。
图片
导致存在两个核心问题:
- 类型不安全:因设计于泛型前,依赖
any
类型,无法保证编译时类型校验,违背 Go 的类型安全原则; - 性能损耗:非指针值转换为
any
需额外内存分配,导致存储字符串键或切片值时效率低下。
解决思路
通过将 sync.Map
和 sync.Pool
改造为泛型类型,可以轻松解决和避免这些问题。
但是由于 Go1 兼容性保障。也就是兼容性问题,考虑 Go 核心团队无法直接修改现有 sync v1 包中的 Map 和 Pool 类型。
解决思路,将主要采取以下两点方法:
- 需要通过泛型重构为强类型设计。
- 新增
sync/v2
包引入泛型版本。例如:Map[K,V]/Pool[T]
,避免命名混乱(例如:PoolOf
的歧义),并支持 v1 到 v2 到平滑迁移。
这样后续大家可以直接通过类似 goimports
工具,直接将 v1 版本迁移至 sync/v2
,不需要手动处理导入路径。
同时可以保留原 v1 包兼容性,可以彻底解决后续类型与性能问题,符合 Go 语言长期演进方向和规范。
具体改造
在 sync/v2
包中,以下类型和函数将与当前 sync
v1 包保持一致(不变):
改造点之一:现有的 Map
类型将被需要两个类型参数的新泛型类型取代。需注意,原 Range
方法将变更为返回迭代器的 All
方法。
如下代码:
改造点之二:现有的 Pool 类型将被一个需要类型参数的新泛型类型取代。
同时新版 Pool 将不再暴露公开的 New
字段,改为通过 NewPool
函数创建实例。该函数接受一个生成新值的函数参数,用于替代原 New
字段的初始化行为。
如下代码:
总结
之前标准库 math/rand/v2
在 Go 核心团队看来,已经取得了不错的成果。泛型在 Go1.18 也输出了(虽然还不完善),Go1 向前兼容性和向后兼容性保障的方式也确立了。
接下来想必 Go 就会每年更新几个 v2 标准库。这次 sync/v2
也是一次不错的改造,解决了不少原有的问题。大家可以小小期待一下。
参考资料
[1]spec: add generic programming using type parameters: https://github.com/golang/go/issues/43651