GO语言标准库的演进迭代原则

超级欧派课程 2024-05-04 04:39:04

go 官方表示此项工作的目标之一是为如何处理标准库中所有v2包确立一套原则与模式。未来几个Go版本并不会一口气出现众多新v2包。我们将逐一处理,确保设定的品质标准可以持续未来十年。有许多包可能完全不需要v2版本。但是,对于那些需要版本升级的包,我们的方法可以归纳为以下三个原则。

新旧版本并存

与之前版本不兼容的包将采用that/package/v2作为其导入路径,就像标准库以外的v2模块一样,遵循语义导入版本号规则。这使得原本包的使用与v2包在同一个程序中共存成为可能,这对逐步过渡新API至关重要。

不同版本的包应该能够在代码中共存的原因主要有以下几点:

兼容性:在现实的开发过程中,引入新版本的包可能会改变某些API或者引入新的特性,这些变化可能会与已有的代码产生冲突。如果不同版本的包可以共存,开发者就可以在不改变已有代码的情况下引入新版本,避免破坏现有的系统。平滑升级:如果新旧版本可以共存,那么开发者就可以逐渐将代码迁移到新版本,而不是一次性将所有的代码都进行升级。这样的过渡可以让开发者有足够的时间来适应新版本,同时也可以在过渡期间识别并解决可能出现的问题。灵活性:在某些情况下,开发者可能同时需要使用新旧两个版本的包。比如,他们可能在一些旧的代码模块中使用旧版本,同时在新的代码模块中使用新版本。如果新旧版本可以共存,那么开发者就有更大的灵活性来组织他们的代码。保障稳定性:引入新版本的包往往意味着存在风险,比如新版本的包可能存在尚未发现的bug,或者其性能还没有被充分验证。如果新旧版本可以共存,那么当新版本的包出现问题时,开发者可以立即回退到旧版本,保障系统的稳定性。

因此,允许不同版本的包在代码中共存是非常重要的,它可以帮助开发者更好地管理代码,同时也能提高代码的稳定性和开发的灵活性。

尊重现有用户以及使用方式

所有的修改必须基于对当前用户和使用情况的尊重:不能引入不必要的变动,无论是对现有包的无谓改动,还是完全需要重新学习的新包。实际运用中,这意味着我们以当前的包作为起点,只对有充分理由且能为用户更新带来价值的变动进行修改。

不能引入无需的变化,无论是形式上对现有包的不必要改动,还是完全需要用户重新学习的全新包。

这个原则的主要考虑因素有:

尊重用户需求:每一次的改变都必须基于对现有用户和他们的实际需求的深入理解。这样可以保证在迭代优化的过程中,始终会在提升用户体验并增加用户价值的方向上进行。稳定性保障:避免了因频繁的无需改动而导致用户的混乱和系统的不稳定,相反,只对有充分理由且对更新用户带来价值的部分进行改变。低学习成本:这个原则保证了改动会以当前包为起点,避免用户需要花费额外的时间和精力去学习全新的包。更好的演进策略:它确保了标准库的演进方向以对现有用户和使用方式的尊重为基础,使得标准库的演进更加目标明确,更加符合用户的实际需要。

这个原则有助于维护用户信任,降低学习成本,并指导标准库往更实用、更稳定的方向发展。

向前兼容:v2包应具备v1包的全部能力

v2包不应遗忘v1的用户。理想情况下,v2包应具备v1包的全部能力。同时,在v2发布时,v1包应被改写为基于v2的薄层封装。这能确保v1版本的现有用户依然可以从v2中的错误修复和性能优化中受益。当然,由于v2引入了一些重大改变,这并不总是可能的,但这仍是我们需要仔细考虑的一点。

保留v1的用户的原因主要有以下几点:

兼容性:许多现有的项目可能已经基于v1版本的库进行了开发和部署,他们可能无法立即升级到v2,因为这可能会需要进行大量的代码修改和测试。保留v1用户可以确保这些项目可以继续正常运行,同时也可以在适当的时候平滑地过渡到v2。学习曲线:对于新来的或者不熟悉v2的用户,v1可能是他们接触和学习的起点。同时,v1对于一些老用户来说已经非常熟悉,他们可能不愿意或者没有必要立即迁移到v2。保留v1用户也就意味着尊重他们的学习选择和使用习惯。维护性:通常情况下,v1版本在发布v2的时候已经非常稳定,并且积累了大量的使用案例和社区资源,如文档和问题解答。这些是无法短时间内完全复制到v2的。 通过保留v1,可以让用户在享受新功能的同时,还能利用到这些已有的社区资源。持续优化:如原文提到的,v1版本应该是v2版本的薄封装,这样v1版本就可以继续从v2中的错误修复和性能优化中受益,也就是说,虽然使用的是旧版本,但是用户依然可以享受到新版本带来的一些优点。

保留v1的用户不仅体现了对用户的尊重,也确保了Go标准库的稳定性和持续优化。同时,也为用户提供了更多的选择,确保了他们可以根据自身的实际情况和需求选择最合适的版本。

以math/rand/v2 这个包为例进行说明

对于math/rand/v2,我们设计了自动初始化种子的v1函数调用v2生成器,但我们无法共享其他代码,因现有代码不符合可重复性。

最终,math/rand 并不是很大的代码库,且无需定期进行维护,所以代码重复问题是可以控制的。在其他环境中,更多的避免重复可能是有价值的。

例如,在进行中的encoding/json/v2设计中,尽管默认语义和API发生了变更,但包内提供了一些配置选项,使v1 API的实现成为可能。最终,当我们发布encoding/json/v2时,v1版的encoding/json将成为其薄层封装,确保那些未从v1迁移的用户可以从v2的优化和安全性修复中受益。

总结

Go的演进策略充分体现了其作为工程型的语言特性,稳定、实用和持续优化是其主要的考虑方向:

稳定性和兼容性:Go被广泛应用在各类底层系统和基础设施中,稳定性和兼容性是其核心的需求。Go的策略保证了在引入新特性和优化的同时,不会对现有的代码产生破坏,使得开发者可以依赖其长期稳定地运行。实用和可维护:Go注重实用性,对于不必要的改变持谨慎态度,这既是出于尊重现有用户,也是为了降低维护成本。暴力升级会给开发者带来额外的学习成本,而且可能引入新的bug,Go的策略避免了这种情况的发生。持续优化:Go的方向是持续优化和改进,但不应牺牲现有用户的利益。新版的优化和修复可以反馈到旧版,使所有用户都能够受益。

因为 golang 是面向工程,面向研发人员而设计的轻量级现代化编程语言,因此其演进方向也是考虑了很多工程特性,这也是 golang 的优势,如果您刚好在学习 golang,我推荐下面这个专栏,里面包含了各种一线生产最佳实践和使用技巧,让你可以快速了解并学会通过 golang 编写符合最佳实践的大型项目。

0 阅读:22

超级欧派课程

简介:感谢大家的关注