Go 1.11

文章目录

新学期开始,虽然不关自己什么事情,但终于能抽出时间来写博客了。

新的Go版本在8月24号就发布了,Release Note:https://golang.org/doc/go1.11

按照老规矩,1.10继续维护到1.12发布为止,还有半年的时间供开发者们适配新版本,下面记下自己感兴趣的部分。

操作系统与架构

Linux维持原样,其他操作系统的要求有增删,Windows最低要求Win7,OpenBSD最低6.2,macOS 最低10.10。

WebAssembly

在刚发布升级时就尝鲜安装了一下,然后本地项目直接无法运行。原因是1.11在GOOS中新增js,GOARCH中新增wasm,于是用户项目中所有***_js.go*_wasm.go**的文件都会被Go tools忽略,需要重命名来解决问题。

RISC-V

GOARCH新增保留字段riscv及riscv64,同上面一样,所有***_riscv.go**的文件也会被忽略

工具

模块,包版本及依赖管理

1.11新增了模块的概念,目前处于实验性支持的状态,通过使用模块,开发人员不再局限于在GOPATH中工作,版本依赖性信息将是显式而轻量级的,构建过程会更可靠和容易复现。

总之目前还没有达到生产水平,也是等待开发者们使用,收集反馈再改进的状态。

import path限制

由于Go的模块支持在命令行中使用@符号赋予特殊含义,所以禁止在go get命令中出现带@符号的import path。

包加载

golang.org/x/tools/go/package包提供了一个用于定位和加载Go源码包的API,目前未合并进标准库,但在许多任务中,会比原先的go/build包更好地支持模块,不需要依赖外部的查询命令来获取包的信息,有利于编写与其他构建系统类似的分析工具。

Build cache支持

1.11仍旧支持手动关闭build cache,但作为消除**$GOPATH/pkg**的一环,它将在1.12中会强制启用。build cache特性会缓存构建结果并复用,上述的模块以及包加载功能需要在它开启的状态下使用。

编译器工具链

(1)更多的函数默认内联,包括panic。

(2)支持行指令中的列信息。

(3)引入了新的包导出数据格式,对于用户透明。

(4)若switch语句中存在未使用的变量,编译器会报错,在gccgogo/types中已经启用。

汇编

amd64架构支持avx512指令集

调试

编译器为优化后的二进制文件生成更多有效的调试信息,包括变量位置、行数、断点位置,这让我们有可能对使用“-N -l”编译指令生成的二进制文件进行调试。调试信息的质量还有一些限制,在后续的版本发布中会有改善。

由于编译器生成了更精确的调试信息,DWARF段被压缩掉,这对于使用ELF工具的的BSD及Linux来说是透明的,Delve调试器已经在所有平台上支持了这个特性,但在macOS与windows上,原生工具只有受限的功能支持,可以在构建时传入**-ldflags=-compressdwarf=false**来关闭该特性。

1.11新增了在调试器中调用Go函数的功能,目前还是实验性支持,例如在一个断点里调用Strings的方法,目前这个功能只能在Delve 1.1.0及以上版本中使用,有点像chisel。

测试

从Go 1.10开始,go test命令会在测试的包中调用go vet命令,在开始测试前检查代码问题。由于vet指令会在运行前使用go/types对代码进行类型检查,未进行类型检查的测试代码会失败。特别是对于一个闭包内部含有未使用变量的测试代码,现在会报“unused variable”错误。

-memprofile标志的值现在默认为“allocs”,它将会记录测试开始后(包括垃圾回收)分配的字节数。

语法检查

之前的类型检查错误只会引起一个警告,并在go vet执行结束时返回状态1,而现在,如果包没有进行类型检查,执行go vet指令会报fatal error。

另外,go vet在对printf的封装进行格式检查时会更健壮,例如将参数传入与格式不匹配的封装函数也会被检查到。

性能调优

得益于新的runtime/trace包的用户标记API,现在我们可以在执行跟踪中记录应用程序级信息,并创建相关goroutine组,go tool trace命令可在跟踪视图和新用户任务或区域分析页面中显示这些信息。

Cgo

从Go 1.10开始,cgo已经将一些C指针类型转译成Go的uintptr类型,包括Darwin平台CoreFoundation中的CFTypeRef,以及Java的JNI接口中的jobject,Go 1.11对这些检测特殊指针类型的代码做了许多改进。

Godoc

Go 1.11将会是最后一个支持godoc命令行指令的版本,后续的版本中godoc将只作为一个网页服务器,用户需要使用go doc(中间带空格)命令替代。

godoc网页服务器现在会显示哪一个Go版本引入了新API特性。

运行时

运行时现在使用稀疏堆布局方式,因此不再限制Go堆的大小(之前的限制是512GB),这也解决了使用**-race**编译或Go与C混编的二进制文件中罕见的“地址空间冲突”问题。

在macOS及iOS上,runtime现在使用libSystem.so库代替直接调用内核的方式,这会使Go二进制文件与未来版本的macOS及iOS更兼容。syscall包仍然执行直接系统调用,在未来的版本中会计划修复这个问题。

性能

还是老样子,虽然改了很多,但不晓得有木有改善,大多数的程序应该会运行的快一点,因为核心库的代码有了更好的代码生成与优化。

math/big包中有许多的性能改善,arm64架构相关的包也一样。

编译器工具链

(1)优化了在使用range遍历map时,删除map元素的代码。

(2)优化了以**append(s, make([]T, n)...)**格式拓展切片的代码。

(3)更积极的边界检查和分支消除策略,现在可以检测到传递关系,例如可以利用i<j以及j<len(s),消除对s[i]的边界检查分支。编译器还可以理解简单的算法,例如s[i-10],并且可以在循环中识别更多的归纳情况。此外,编译器现在使用边界信息来更积极地优化移位操作。

核心库

许许多多的微小修改