大家好,我是煎鱼。
在五一假期的第一天,Go 核心团队也没有闲着,@Russ Cox 直接在官方博客发布了《Evolving the Go Standard Library with math/rand/v2》这篇文章。
图片
其部分内容是对本次做 math/rand/v2 标准库升级的内容进行再度陈述,有兴趣的小伙伴可以阅读我之前写的《Go1.22 新特性:新的 math/rand/v2 库,更快更标准!》,能够知悉全貌。
本文的重点是对另外的 Go 标准库 v2 的指导思想和规划进行分享。
之前:标准库 v1 问题
自 Go1 在 2012 年 3 月发布以来,对标准库的修改一直受到 Go1 的兼容性承诺的约束。
图片
总体而言,Go1 兼容性保障对 Go 用户来说是一个福音,它为生产系统、文档、教程、书籍等提供了一个稳定的基石。
然而随着时间的推移,Go 核心团队意识和发现原始 API 中,存在着许多错误无法以兼容的方式修复。
包括在其他场景下,Go 的最佳实践和约定已经发生了变化。我们需要一个可推进的计划来做出重要的、破坏性的变更。
为此,Go 1.22 新增的 math/rand/v2 包,这是标准库中的第一个 “v2” 包。它为 math/rand API 带来了必要的改进。
更重要的是:它为我们如何根据需要修订其他标准库包树立了榜样。
未来:标准库 v2 演进原则
基本准则
这项工作的目标之一是:为标准库中所有 v2 包的处理方式建立原则和模式。
在接下来的几个 Go 版本中,Go 核心团队承诺不会有大量的 v2 包涌现。相反,他们将每一次只处理一个包,提高设计质量。
确保新的标准库 v2 设定的质量标准能够持续十年。(可能有许多包根本不需要 v2)
三个设计原则
对于那些确实需要 v2 版本的包,我们将会归结为三个设计原则去实施。
具体如下:
1、不兼容的新版本软件包将使用 /package/v2 作为导入路径:就像标准库之外的 v2 模块一样遵循语义导入版本化。这样原始软件包 v1 和 v2 软件包就可以在一个程序中共存,这对于逐步转换到新的应用程序接口至关重要。
2、所有更改都必须以尊重现有用法和用户为基础:我们绝不能引入不必要的变化,无论是对现有软件包的不必要更改,还是必须学习的全新软件包。在实践中,这意味着我们要以现有软件包为起点,只对动机明确、价值合理的软件包进行修改。
3、v2 标准库不能把 v1 用户抛在后面,完全不管了。在理想情况下,v2 软件包应能做 v1 软件包能做的一切事情,而当 v2 发布时,v1 软件包应被重写为 v2 的薄封装。这将确保现有的 v1 软件包继续受益于 v2 中的错误修复和性能优化,也保证了 v1 的兼容性。
意外考量
相较于 v1, v2 的包将会引入破坏性的变化,想让 v1 被重写为 v2 的薄封装,并不总是可行的,在设计上这始终是需要慎重考虑的。
像是本次新增的 math/rand/v2,我们将 rand 中 auto-seeded v1 函数调用 v2 生成器,但由于重复性违规,我们无法共享其他代码。最终,math/rand 改动的代码量并不大,也不需要定期维护,因此重复是可控的。
在其他情况下,为避免重复做更多的工作可能是值得的。例如:在 encoding/json/v2 的设计(仍在进行)中,虽然默认语义和 API 都发生了变化,但软件包提供的配置项可以实现 v1 API。
当我们最终发布 encoding/json/v2 时,encoding/json (v1) 将成为它的一个薄包装,确保不从 v1 迁移的用户仍能受益于 v2 中的优化和安全修复。
总结
通过阅读本文的标准库 v2 的设计讲解,能够感受到其实 @Russ Cox 已经对 Go 兼容性这块做好了规划。基本是先动 Go1 兼容性前后保障的准则,再动标准库。同时标准库 v2 要兼容 v1 的使用,不能直接就是完全不维护了。
这样对于用户的得益虽然是较大的,但对于 Go 核心团队来讲,维护的工作量和可能出现的程序意外(BUG)的概率也会变大,因为要兼容的新老场景都变多了。
不论怎么说,未来这将会出现。大家可以一起见证 Go 标准库 v2 接下来的发展!我猜 json v2 包要快转正了。