Skip to content

Latest commit

 

History

History
157 lines (90 loc) · 12.4 KB

201602 Go 1.6 Release Notes.md

File metadata and controls

157 lines (90 loc) · 12.4 KB

Go1.6发布说明

Go 1.6 介绍

在1.5发布6个月后,Go再次发布了最新的v1.6.其主要变化体现在语言,运行时和库函数的实现上,但在Go语言规范上没有变化.和往常一样,本次发布仍然保持Go 1时的兼容性承诺.我们预计几乎所有的go程序都可以像以前一样编译和运行.

本次发布新增了Linux on 64-bit MIPS和Android on 32-bit x86的移植;制定了在C中共享Go指针的规则;支持透明和自动地使用HTTP/2;新的模板重用机制.

语言变化

本次发布没有语言变化.

移植

Go1.6在linux on 64-bit MIPS(linux/mips64 and linux/mips64le)上添加了实验性的移植支持.这些移植支持cgo,但仅支持internal连接(ps: C语言连接3属性:external,internal,none).

Go1.6也在Android on 32-bit x86(android/386)上进行了实验性的移植.

在FreeBSD上,Go1.6默认使用clang而不是gcc,做为外部的C编译器.

在linux的小端64-bit PowerPC(linux/ppc64le)上,Go1.6已支持在cgo中使用external连接,且功能也大致完整了.

在NaCI上,Go1.5需要pepper-41版本的SDK,而Go1.6需要更高的版本.

在 32 位 x86 系统中使用 --dynlink 或者 --shared 编译模式,寄存器 CX 被特定内存引用覆盖,可通过编写汇编指令来更改这个行为,详情请看这里.

工具

Cgo

在cgo中有一个重大改变和一个小改动.

主要的变化是定义了在C中共享Go指针的规则,以确保C语言代码和Go的gc可以共存.简单的说,Go和C可以共享由Go分配的内存,即指向该内存的Go指针可通过作为cgo调用的一部分传递给C,但是,该内存本身不再属于Go分配的内存,同时调用返回后,C不再保留该指针.这些规则在程序执行中由运行时负责检查:如果运行时检测到违规,它会打印诊断信息并使程序崩溃.该检查可通过设置环境变量GODEBUG=cgocheck=0来禁用,但需要注意绝大多数被检查出来的代码有与gc存在这样或那样的细微的不兼容.禁用检查通常会导致更多的神秘故障.修复有问题的代码应该优于关闭检查,想了解更多信息请查看cgo的文档.

较小的变化是,增加了明确的C.complexfloat和C.complexdouble类型,与Go本身的complex64和complex128区分开来.和其他数值类型一样,C的complex类型和Go的complex类型不再可以互换.

编译工具链

编译工具链几乎不变.在内部,最显著的变化是解析器现在是手写的,而不是由yacc生成.

编译器,连接器和go命令有一个新的标志-msan,类似于-race且仅在linux/amd64下可用,其提供了和Clang MemorySanitizer的互操作性.这样的互操作在程序中包含C或者C++代码时非常有用.

连接器有一个新的选项-libgcc,在连接cgo代码时可用来设置C编译器支持库的预期位置.该选项仅在使用-linkmode=internal时有效,并且可以设置为none来禁用支持库.

从Go1.5开始,构建模式的实现已经扩大到了更多的系统.本次发布的版本在android/386, android/amd64, android/arm64, linux/386, and linux/arm64上添加了c-shared模式;在linux/386, linux/arm, linux/amd64, and linux/ppc64le上添加了shared模式;以及在android/386, android/amd64, android/arm, android/arm64, linux/386, linux/amd64, linux/arm, linux/arm64, and linux/ppc64le上添加的新pie模式(生成位置无关的可执行文件).更多信息请查看设计文档.

作为提醒,连接器的-X标志已经在Go1.5中发生了变化.在Go1.4甚至更早的版本中,它需要两个参数,例如:

-X importpath.name value

在Go1.5中添加了一个使用单个参数的替代语法,通过使用name=value这样的键值对:

-X importpath.name=value

在Go1.5中旧的语法仍旧有效,但会有提示使用新语法的警告信息.在GO1.6中继续有效并打印警告信息,但在Go1.7中将移除旧语法.

Gccgo

GCC和Go项目的发布时间并不一致.GCC5包含了Go1.4的gccgo,下一版的Go1.6则会包含Go1.5的gccgo.因此,Go1.6可能要到GCC7才能被采纳.

go命令

go命令的基本操作不变,但也有些值得一提的变化.

Go1.5时通过将环境变量GO15VENDOREXPERIMENT设为1来实验性地引入vendoring的支持,在Go1.6中将继续支持该特性,且不再是实验性的,已变为默认设置,但可通过设置GO15VENDOREXPERIMENT为0来禁用.Go1.7移除该环境变量.

默认启用vendoring最可能引发的问题是因为源码中已包含一个叫vendor的文件夹,但其中的内容不希望按照新的vendoring语义来解析.在这种情况下,最简单的解决办法是重命名文件夹(即文件名不再是vendor),并更新相关引用的路径.

更多vendoring的信息,请查看go命令文档设计文档.

新的构建标志-msan让go编译器支持LLVM的memory sanitizer.这样做的目的主要是可用memory sanitizer检查连接到的C或者C++代码.

go doc 命令

Go1.5引入了go doc命令,通过包名即可查看其使用方法.比如go doc http.在模糊情况下,Go1.5根据字典排序选取接近的导入路径??.在Go1.6中采用更短的导入路径来取代字典比较??.这种变化带来的影响是原先的包内容将优先于vendor内容??.成功的搜索往往会让程序跑等更流畅.

go vet 命令

go vet命令现在诊断传递给Printf函数的作为参数的函数或值,比如用f替代f()时??.

性能

和以前一样,变动是普遍和多样的,以至于很难精准的描述性能变化.某些程序可能运行地更快,有些更慢.Go1.6在Go 1基准测试套件中比Go1.5更快了.GC停顿比Go1.5更短了,在使用大量内存的程序上特别明显.

显著的实现优化给包compress/bzip2, compress/gzip, crypto/aes, crypto/elliptic, crypto/ecdsa,和sort带来了超过10%的性能改进.

核心库

HTTP/2

Go1.6的net/http包透明地支持全新的HTTP/2协议.Go的客户端和服务器在使用https时将自动使用HTTP/2.Go中并没有特定的可导出的API来处理HTTP/2,就像没有特定的可导出API来处理HTTP/1.1一样.

程序可通过将Transport.TLSNextProto(针对客户端)或Server.TLSNextProto(针对服务端)设置为非nil的空map来禁用HTTP/2.

程序可通过导入golang.org/x/net/http2包来调整HTTP/2的细节,特别是它的ConfigureServerConfigureTransport函数.

运行时

运行时添加了轻量的,更有效的并发误用检查的maps.和以前一样,如果一个goroutine写入map,其他goroutine应不能并发地读写该map.如果运行时监测到这种情况,它将打印诊断信息并crash程序.要了解更多信息应在race detector(可以更加可靠地识别出竞争并给出更多的信息)下运行程序.

程序panic时,运行时现在只打印正在运行的goroutine栈的信息,不再是所有的goroutines.通常只有当前的goroutine是和panic相关的,所以省略其他会显著地减少不相干的crash信息.如果想查看crash中所有的goroutines栈信息,可将环境变量GOTRACEBACK设为all或重新运行程序在crash前调用debug.SetTraceback.了解更多信息可查看运行时的文档.

更新:现在未捕捉到的panic使整个程序dump时,例如,一个超时被检测到或明确地处理一个收到的信号,允许在panic前调用debug.SetTraceback("all").搜索signal.Notify的使用可能有利于辨认出这些代码.

在Windows上,Go在1.5及早先的版本中,通过在启动时调用timeBeginPeriod(1)强制将Windows全局计时器的精度设为1ms.现在Go不再需要这个来优化调度器的性能,同时不再允许在其他系统上修改全局精度(其会导致其他问题),所以已经移除该调用.

当使用-buildmode=c-archive-buildmode=c-shared来创建一个静态或动态库时,信号的处理方式已经发生改变.在Go1.5中,静态或动态库内置一个信号处理器来处理大多数信号.在Go1.6中内置的信号处理器仅在runtime panic时处理代码中的同步信号:SIGBUS, SIGFPE, SIGSEGV.查看os/signal可获得更多细节.

反射

reflect包已经解决了一个长期存在于gc和gccgo工具链中关于内嵌的不可导出的struct类型包含可导出字段时的不兼容问题.使用反射来获取数据结构的代码,特别是使用encoding/jsonencoding/xml包实现序列化的代码,可能需要更新.

问题出现在使用反射一个内嵌不可导出的struct类型字段时变成可导出的该struct类型.在这种情况下,reflect会错误地认为内嵌字段是可导出的(通过返回一个空的Field.PkgPath).现在,它会正确地认为该字段是不可导出的,但是会忽略这一事实当可导出字段包含该struct时.

更新: 通常情况下,早先代码通过使用

f.PkgPath != ""

来排除不可用的字段,现在需要使用

f.PkgPath != "" && !f.Anonymous

例如,查看encoding/jsonencoding/xml的实现.

排序

sort包,Sort函数的实现已经被重写,通过在调用Interface接口的LessSwap方法时节省相应的总时间以带来10%性能的提升.新算法会选择不同的排序方式,以前是通过比较值是否相等,即成对调用Less(i, j)和Less(j, i)是否为false来实现.

更新: Sort的实现不再保证相同值的最终顺序,但新的行为仍可能打破这种期望以实现特定的排序.这样的程序会完善它们的Less实现或使用Stable以获得期望的顺序或者,这等于保留了原始相同值的输入顺序.

模板

text/template包有两个显著的新功能,使得编写模板更加容易.

首先,它可以去除环绕在模板action({{}})周围的空格,使模板定义更有可读性.一个减号出现在action的开头说明去除该action前的空格,一个减号出现在action的结尾说明去除该action后的空格.例如,模板

{{23 -}}
   <
{{- 45}}

会格式化为23<45.

其次,新的action{{block}},和允许重新定义一个已有模板相结合,提供了一种简单的方式来定义模板的片段,其可以在不同的实例中被替换.在text/template中有一个案例演示了这一新功能.

标准库的次要变化

请查看原文,这里略.