Go 1 与 Go 程序的未来
引言
Go 版本 1(简称 Go 1)的发布,是这门语言发展的一个主要里程碑。Go 1 是一个稳定的平台,可用于发展以 Go 编写的程序和项目。
Go 1 定义了两件事:首先,是语言的规范;其次,是一组核心 API 的规范,即 Go 库的“标准包”。Go 1 版本包含了它们的实现,形式为两个编译器套件(gc 和 gccgo)以及核心库本身。
我们期望,为 Go 1 规范编写的程序,在该规范的生命周期内,将能够持续正确地编译和运行,无需更改。在未来的某个不确定时间点,可能会出现 Go 2 规范,但在那之前,即使 Go 1 的未来“点”版本(Go 1.1, Go 1.2 等)发布,今天能运行的 Go 程序也应能继续运行。
兼容性是在源代码层面。已编译包的二进制兼容性在各版本之间不作保证。在一个点版本发布后,Go 源代码将需要重新编译以链接到新版本。
API 可能会增长,增加新的包和功能,但不会以破坏现有 Go 1 代码的方式进行。
预期
虽然我们预期绝大多数程序能随时间推移保持这种兼容性,但无法保证未来的任何更改都不会破坏任何程序。本文旨在设定对未来 Go 1 软件兼容性的预期。一个今天能编译和运行的程序,在未来的点版本发布后可能会失败,有多种原因。这些情况都很少见,但值得记录。
- 安全。规范或实现中可能会发现安全问题,其解决方案需要破坏兼容性。我们保留解决此类安全问题的权利。
- 未指明行为。Go 规范试图明确语言的大部分属性,但有些方面是未定义的。依赖此类未指明行为的程序可能会在未来版本中被破坏。
- 规范错误。如果需要解决规范中的不一致或不完整之处,解决问题可能会影响现有程序的含义或合法性。我们保留解决此类问题的权利,包括更新实现。除安全问题外,不会对规范进行不兼容的更改。
- Bug。如果编译器或库存在违反规范的 bug,依赖于该错误行为的程序在 bug 被修复后可能会被破坏。我们保留修复此类 bug 的权利。
- 结构体字面量。为了在之后的点版本中添加新功能,可能需要向 API 中导出的结构体添加字段。使用未指定键的结构体字面量(如 `pkg.T{3, "x"}`)创建这些类型值的代码,在此类更改后将无法编译。然而,使用指定键的字面量(`pkg.T{A: 3, B: "x"}`)的代码在此类更改后将继续编译。我们将以允许指定键的结构体字面量保持兼容的方式更新此类数据结构,尽管未指定键的字面量可能无法编译。(还有涉及嵌套数据结构或接口的更复杂情况,但它们有相同的解决方法。)因此,我们建议,类型在单独包中定义的复合字面量应使用指定键的表示法。
- 方法。与结构体字段一样,可能需要向非接口类型添加方法。在某些情况下,例如当该类型与另一类型一起嵌入到一个结构体中时,新方法的添加可能会通过与另一个嵌入类型的现有方法产生冲突而破坏该结构体。我们无法防范这种罕见情况,并且不保证在这种情况下能兼容。
- 点导入。如果一个程序使用 `import . "path"` 导入一个标准包,未来版本中在该导入包中定义的额外名称可能会与程序中定义的其他名称冲突。我们不建议在测试之外使用 `import .`,使用它可能会导致程序在未来版本中无法编译。
- 使用 `unsafe` 包。导入 `unsafe` 包的程序可能依赖于 Go 实现的内部属性。我们保留对实现进行可能破坏此类程序的更改的权利。
当然,对于所有这些可能性,一旦出现,我们都会在可行的情况下努力更新规范、编译器或库,而不影响现有代码。
这些同样的考虑也适用于连续的点版本。例如,在 Go 1.2 下运行的代码应与 Go 1.2.1、Go 1.3、Go 1.4 等兼容,但未必与 Go 1.1 兼容,因为它可能使用了仅在 Go 1.2 中添加的功能。
在版本之间添加的功能,可在源代码仓库中获得但尚未成为带编号的二进制版本的一部分,正处于积极开发中。对于使用此类功能的软件,在它们被发布之前,不作任何兼容性承诺。
最后,虽然这不是一个正确性问题,但程序的性能可能会受到其所依赖的编译器或库实现变化的影响。无法保证一个给定程序在不同版本之间的性能。
尽管这些预期适用于 Go 1 本身,我们希望在开发基于 Go 1 的外部软件时也能有类似的考虑。
子仓库
主 go 树的子仓库中的代码,例如 golang.org/x/net,可能会在更宽松的兼容性要求下开发。然而,这些子仓库将被适当地打上标签,以识别与 Go 1 点版本兼容的版本。
操作系统
无法保证与操作系统接口的长期兼容性,因为这些接口由外部方更改。因此,`syscall` 包不在本文所作保证的范围之内。自 Go 1.4 版本起,`syscall` 包已被冻结。系统调用接口的任何演进都必须在其他地方得到支持,例如在 go.sys 子仓库中。有关详情和背景,请参阅此文档。
工具
最后,Go 工具链(编译器、链接器、构建工具等)正在积极开发中,其行为可能会改变。这意味着,例如,依赖于工具位置和属性的脚本可能会因点版本发布而被破坏。
除了这些注意事项,我们相信 Go 1 将为 Go 及其生态系统的发展奠定坚实的基础。