Go 1 与 Go 程序的未来
引言
Go 1 版本(简称 Go 1)的发布是该语言发展历程中的一个重要里程碑。Go 1 是一个稳定的平台,用于发展使用 Go 编写的程序和项目。
Go 1 定义了两件事:首先是语言的规范;其次是一套核心 API 的规范,即 Go 库的“标准包”。Go 1 版本以两个编译器套件(gc 和 gccgo)的形式提供了它们的实现,以及核心库本身。
其意图是,按照 Go 1 规范编写的程序,在该规范的整个生命周期内,能够持续正确地编译和运行,无需更改。在某个不确定的时间点,可能会出现 Go 2 规范,但在此之前,今天能够工作的 Go 程序,即使未来出现 Go 1 的“点”版本(Go 1.1、Go 1.2 等),也应该继续工作。
兼容性是在源代码层面保证的。不保证编译后的包在不同版本之间具有二进制兼容性。在点版本发布后,Go 源代码需要重新编译以链接到新版本。
API 可能会增长,获得新的包和特性,但不会以破坏现有 Go 1 代码的方式进行。
预期
尽管我们预计绝大多数程序将随着时间的推移保持这种兼容性,但无法保证未来的任何更改都不会破坏任何程序。本文档旨在为未来 Go 1 软件的兼容性设定预期。有多种情况可能导致今天能编译运行的程序在未来的点版本发布后无法编译运行。这些情况都不太可能发生,但值得记录在案。
- 安全性。规范或实现中可能出现安全问题,其解决需要破坏兼容性。我们保留解决此类安全问题的权利。
- 未指定行为。Go 规范试图明确语言的大多数属性,但某些方面是未定义的。依赖此类未指定行为的程序可能在未来的版本中被破坏。
- 规范错误。如果需要解决规范中的不一致或不完整,解决该问题可能会影响现有程序的含义或合法性。我们保留解决此类问题的权利,包括更新实现。除安全问题外,不会对规范进行不兼容的更改。
- 缺陷。如果编译器或库存在违反规范的缺陷,依赖该缺陷行为的程序可能在缺陷修复后被破坏。我们保留修复此类缺陷的权利。
- 结构体字面量。为了在后续点版本中添加特性,可能需要向 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 及其生态系统开发的坚实基础。