Go 1.4 Release Notes

Introduction to Go 1.4

最新的Go版本1.4版按计划在1.3版本之后六个月到货.

它仅包含一个微小的语言更改,形式为for - range循环的向后兼容简单变体,并且可能涉及到指向指针的方法对编译器进行了重大更改.

该发行版主要关注实现工作,改进垃圾收集器并为在接下来的几个发行版中推出完全并发的收集器做准备. 现在堆栈是连续的,在必要时重新分配,而不是链接到新的"段"上; 因此,此版本消除了臭名昭著的"热堆栈拆分"问题. 有一些新工具可用,其中包括go命令中对构建时源代码生成的支持. 该版本还增加了对Android和Native Client(NaCl)上的ARM处理器以及Plan 9上的AMD64的支持.

与往常一样,Go 1.4保留了兼容性承诺,当移至1.4时,几乎所有内容都将继续编译并运行而无需更改.

Changes to the language

For-range loops

直到Go 1.3, for - range循环有两种形式

for i, v := range x {
	...
}

and

for i := range x {
	...
}

如果一个未在循环值感兴趣,仅迭代本身,它仍然有必要提及变量(可能是空白的标识符 ,如在for _ = range x ),因为表单

for range x {
	...
}

在语法上是不允许的.

这种情况似乎很尴尬,因此从Go 1.4开始,无变量形式现在是合法的. 模式很少出现,但是这样做时代码可以变得更干净.

更新 :该更改与现有Go程序严格向后兼容,但是可能需要修改分析Go解析树的工具以接受此新格式,因为RangeStmtKey字段现在可能为nil .

Method calls on **T

鉴于这些声明,

type T int
func (T) M() {}
var x **T

gcgccgo接受了方法调用

x.M()

这是指针x的双重取消引用. Go规范允许自动插入单个取消引用,但不能插入两个,因此根据语言定义,此调用是错误的. 因此在Go 1.4中是不允许的,这是一个重大更改,尽管几乎不会影响任何程序.

更新 :依赖旧的错误行为的代码将不再编译,但可以通过添加显式取消引用来轻松修复.

Changes to the supported operating systems and architectures

Android

Go 1.4可以为运行Android操作系统的ARM处理器构建二进制文件. 它还可以构建.so库,Android应用程序可以使用移动子存储库中的支持包来加载.so库. 这里提供了该实验端口计划的简要说明.

NaCl on ARM

以前的版本引入了对本机客户端(NaCl)的支持,即使用32位指针(GOARCH = amd64p32)对32位x86( GOARCH=386 )和64位x86进行支持. 1.4版本增加了NaCl对ARM(GOARCH = arm)的支持.

Plan9 on AMD64

如果内核支持nsec系统调用并使用4K页面,则此版本增加了对AMD64处理器上的Plan 9操作系统的支持.

Changes to the compatibility guidelines

这种unsafe软件包允许人们通过利用实现的内部细节或数据的机器表示来击败Go的类型系统. 从未明确指出Go兼容性指南中指定的unsafe对兼容性的含义. 答案当然是,我们不能保证对执行不安全操作的代码具有兼容性.

我们已经在发行版随附的文档中澄清了这种情况. 现在, Go兼容性指南unsafe软件包的文档已明确规定,不保证不安全代码仍然兼容.

更新 :技术没有改变; 这只是说明文件.

Changes to the implementations and tools

Changes to the runtime

在Go 1.4之前,运行时(垃圾收集器,并发支持,接口管理,映射,切片,字符串等)大部分是用C编写的,并带有一些汇编程序支持. 在1.4中,许多代码已转换为Go,以便垃圾收集器可以在运行时扫描程序堆栈,并获得有关哪些变量处于活动状态的准确信息. 此更改很大,但是对程序没有语义影响.

此重写使1.4中的垃圾回收器可以完全精确,这意味着它知道程序中所有活动指针的位置. 这意味着堆将更小,因为不会有误报使非指针保持活动状态. 其他相关更改也减少了堆大小,与以前的版本相比,堆大小总体减小了10%-30%.

结果是堆栈不再被分段,从而消除了"热拆分"问题. 当达到堆栈限制时,将分配一个更大的新堆栈,将goroutine的所有活动帧都复制到那里,并更新该堆栈中的所有指针. 在某些情况下,性能可能会明显提高,并且总是可以预测的. 详细信息可在设计文档中找到 .

连续堆栈的使用意味着堆栈可以在不触发性能问题的情况下开始变小,因此goroutine堆栈的默认开始大小在1.4中已从8192字节减少到2048字节.

在为计划于1.5版本发布的并发垃圾收集器做准备时,现在通过称为写屏障的函数调用完成对堆中指针值的写操作,而不是直接从更新值的函数中进行写操作. 在此下一个发行版中,这将允许垃圾收集器在运行时调解对堆的写入. 此更改对1.4中的程序没有语义影响,但已包含在发行版中以测试编译器及其产生的性能.

接口值的实现已被修改. 在早期版本中,接口包含一个单词,该单词可以是指针,也可以是一个单词的标量值,具体取决于存储的具体对象的类型. 对于垃圾回收器,此实现存在问题,因此从1.4开始,接口值始终包含一个指针. 在运行的程序中,大多数接口值无论如何都是指针,因此效果很小,但是在接口中存储整数(例如)的程序将看到更多分配.

从Go 1.3开始,如果运行时找到了应该包含有效指针但明显包含无效指针(例如,值3)的内存字,则运行时将崩溃. 在指针值中存储整数的程序可能会违反此检查并崩溃. 在Go 1.4中,设置GODEBUG变量invalidptr=0可以禁用崩溃作为一种解决方法,但是我们不能保证以后的发行版能够避免崩溃. 正确的解决方法是将代码重写为别名整数和指针.

Assembly

汇编程序cmd/5acmd/6acmd/8a接受的语言进行了几处更改,主要是为了更轻松地将类型信息传递给运行时.

首先, textflag.h定义TEXT指令标志的textflag.h文件从链接器源目录复制到标准位置,以便可以将其包含在simple指令中

#include "textflag.h"

更重要的变化在于汇编源如何定义必要的类型信息. 对于大多数程序而言,将数据定义( DATAGLOBL指令)从汇编中移出到Go文件中并为每个汇编函数编写Go声明就足够了. 组装文档描述了要做什么.

更新 :从旧位置包含textflag.h程序集文件仍将起作用,但应进行更新. 对于类型信息,大多数组装例程将不需要更改,但应检查所有内容. 需要特别注意定义数据的程序集源文件,具有非空堆栈框架的函数或返回指针的函数. 必要的(但简单的)更改说明在组装文档中 .

有关这些更改的更多信息,请参见组装文档 .

Status of gccgo

GCC和Go项目的发布时间表不一致. GCC 4.9版包含gccgo的Go 1.2版本. 下一个版本GCC 5可能会带有Go 1.4版本的gccgo.

Internal packages

Go的软件包系统使将程序结构化为具有清晰边界的组件变得容易,但是只有两种访问方式:本地(未导出)和全局(导出). 有时,人们希望拥有未导出的组件,例如,避免获取客户端的代码接口,这些接口是公共存储库的一部分,但不打算在其所属的程序外部使用.

Go语言没有能力执行这种区分,但是从Go 1.4开始, go命令引入了一种机制来定义"内部"包,这些包可能无法由其所在的源子树之外的包导入.

To create such a package, place it in a directory named internal or in a subdirectory of a directory named internal. When the go command sees an import of a package with internal in its path, it verifies that the package doing the import is within the tree rooted at the parent of the internal directory. For example, a package .../a/b/c/internal/d/e/f can be imported only by code in the directory tree rooted at .../a/b/c. It cannot be imported by code in .../a/b/g or in any other repository.

对于Go 1.4,内部打包机制是针对主Go存储库实施的; 从1.5开始,它将对任何存储库强制执行.

该机制的完整细节在设计文档中 .

Canonical import paths

代码通常位于由github.com类的公共服务托管的存储库中,这意味着包的导入路径以托管服务的名称github.com/rsc/pdf ,例如github.com/rsc/pdf . 可以使用现有机制来提供"自定义"或"虚荣"导入路径,例如rsc.io/pdf ,但这会为包创建两个有效的导入路径. 这是一个问题:一个人可能会在一个程序中无意间通过两个不同的路径导入包,这很浪费. 错过对软件包的更新,因为未识别出所使用的路径已过期; 或通过将软件包移至其他托管服务来破坏使用旧路径的客户端.

Go 1.4在Go源代码中为package子句引入了一个注释,用于标识该包的规范导入路径. 如果尝试使用非规范路径导入,则go命令将拒绝编译导入包.

语法很简单:在包装行上添加识别性注释. 对于我们的示例,package子句为:

package pdf // import "rsc.io/pdf"

有了这个, go命令将拒绝编译导入github.com/rsc/pdf的软件包,以确保可以在不破坏用户的情况下移动代码.

该检查是在编译的时候,而不是下载的时间,所以如果go get失败,因为这种检查,误导入的包已经被复制到本地计算机,应该手动删除.

为了补充此新功能,已在更新时添加了检查以验证本地包的远程存储库是否与其自定义导入的相匹配. 如果自首次下载以来,软件包的远程存储库已更改, go get -u命令将无法更新软件包. 新的-f标志将覆盖此检查.

更多信息在设计文档中 .

Import paths for the subrepositories

Go项目子存储库( code.google.com/p/go.tools等)现在可以在自定义导入路径下使用,代替code.google.com/p/go. 使用golang.org/x/ ,如golang.org/x/tools . 我们将在2015年6月1日左右在代码中添加规范的导入注释,届时Go 1.4及更高版本将停止接受旧的code.google.com路径.

更新 :从子存储库导入的所有代码都应更改为使用新的golang.org路径. Go 1.0及更高版本可以解析和导入新路径,因此更新不会破坏与旧版本的兼容性. 未更新的代码将于2015年6月1日左右停止使用Go 1.4进行编译.

The go generate subcommand

go命令具有一个新的子命令go generate ,以在编译之前自动运行工具以生成源代码. 例如,它可以被用来运行yacc上的编译器的编译器.y文件以生成转到源文件执行语法,或自动的生成String用于使用所述新类型的常量方法在工具golang.org/x/tools存储库.

有关更多信息,请参见设计文档 .

Change to file name handling

构建约束(也称为构建标签)通过包含或排除文件来控制编译(请参阅文档/go/build ). 编译也可以通过文件本身的名称来控制,方法是通过在文件后缀" .go或" .s之前加一个下划线以及体系结构或操作系统的名称来"标记"文件. 例如,仅当目标处理器是ARM​​时才编译文件gopher_arm.go .

在Go 1.4之前,类似地标记了一个名为arm.go的文件,但是当添加新的体系结构时,此行为可能会破坏源,从而导致文件突然被标记. 因此,在1.4版中,仅当标签(体系结构或操作系统名称)前面带有下划线时,才会以这种方式对文件进行标签.

更新 :依赖于旧行为的软件包将不再正确编译. 名称为windows.goamd64.go类的文件应在源中添加显式构建标记,或重命名为os_windows.gosupport_amd64.go .

Other changes to the go command

There were a number of minor changes to the cmd/go command worth noting.

Changes to package source layout

In the main Go source repository, the source code for the packages was kept in the directory src/pkg, which made sense but differed from other repositories, including the Go subrepositories. In Go 1.4, the pkg level of the source tree is now gone, so for example the fmt package's source, once kept in directory src/pkg/fmt, now lives one level higher in src/fmt.

更新 :诸如godoc用于发现源代码的工具需要了解新位置. Go团队维护的所有工具和服务均已更新.

SWIG

由于此版本中的运行时更改,Go 1.4需要SWIG 3.0.3.

Miscellany

标准存储库的顶级misc目录,用于包含Go对编辑器和IDE的支持:插件,初始化脚本等. 维护这些文件变得很耗时,并且需要外部帮助,因为列出的许多编辑器未被核心团队成员使用. 这也要求我们决定哪个插件最适合给定的编辑器,即使对于我们不使用的编辑器也是如此.

整个Go社区更适合管理此信息. 因此,在Go 1.4中,此支持已从存储库中删除. 取而代之的是,在Wiki页面上有精选的,内容丰富的列表.

Performance

大多数程序在1.4中的运行速度大约与1.3中相同或稍快; 有些会稍微慢一些. 有很多更改,因此很难精确地预期.

As mentioned above, much of the runtime was translated to Go from C, which led to some reduction in heap sizes. It also improved performance slightly because the Go compiler is better at optimization, due to things like inlining, than the C compiler used to build the runtime.

垃圾收集器的速度加快了,从而导致了可观的垃圾重载程序改进. 另一方面,新的写障碍会再次降低速度,通常降低的速度大约相同,但是根据它们的行为,某些程序可能会变慢或变快.

影响性能的库更改记录在下面.

Changes to the standard library

New packages

此版本中没有新软件包.

Major changes to the library

bufio.Scanner

bufio软件包中的Scanner类型已修复了一个错误,该错误可能需要更改自定义split functions . 该错误使得无法在EOF上生成空令牌. 该修复程序更改了拆分功能看到的最终条件. 以前,如果没有更多数据,扫描将在EOF停止. 从1.4版本开始,在输入耗尽后,将在EOF处一次调用split函数,因此split函数可以生成最终的空令牌,如文档所述.

更新 :可能需要修改自定义拆分功能以在EOF处处理空令牌.

syscall

现在, syscall软件包已冻结,除了维护核心存储库所需的更改之外. 特别是,它将不再扩展为支持核心未使用的新的或不同的系统调用. 原因在单独的文档中进行详细描述.

新subrepository, golang.org/x/sys ,已经建立,以作为新的发展对所有内核支持的系统调用的位置. 它具有更好的结构,具有三个软件包,每个软件包包含UnixWindowsPlan 9之一的系统调用的实现. 这些软件包将更加慷慨地进行组织,接受所有反映那些操作系统中内核接口的合理更改. 有关更多信息,请参见上面提到的文档和文章.

更新 :现有程序不会受到影响,因为syscall软件包与1.3发行版基本没有变化. 要求系统调用不在syscall软件包中的未来开发应golang.org/x/sysgolang.org/x/sys .

Minor changes to the library

下表总结了对该库的一些较小更改,主要是新增内容. 有关每个更改的更多信息,请参见相关的软件包文档.

by  ICOPY.SITE