原文链接

1.8简介

       Go语言1.8版本的Release在时隔1.7六个月后发布了。大多数改变集中在工具链、运行时、库函数的实现。也有两处语言定义的小变化。一如往常,这个版本保持了Go语言1.x版本的兼容了。所有的gopher继续像往常一样编译、运行golang。

       这个版本:

  • 增加了对32位MIPS(一种处理器架构)的支持
  • 更新了编译器后端(也就是1.7发布的基于SSA的新后端)以生成效率更好的代码
  • 通过消除STW栈重扫(stop-the-world stack rescanning)减少GC停顿,
  • 增加http/2 push支持
  • 增加http graceful shutdown
  • 增加更多的context支持
  • 增加对mutex的profiling
  • 简化对slice的排序。

语言的变化

       当隐式地将一个结构体实例转换到另一个结构体类型时,在go1.8中,字段tag会被忽略。因此,两个只有tag有区别的结构体就可以互相转换。

func example() {
	type T1 struct {
		X int `json:"foo"`
	}
	type T2 struct {
		X int `json:"bar"`
	}
	var v1 T1
	var v2 T2
	v1 = T1(v2) // 现在合法
}

       语言定义现在只要求实现支持最多16位(16-bit)指数的浮点常量。这不影响’gc’或’gccgo’编译器,两者都支持32位。

工具

汇编

针对64位x86系统,增加了一下指令VBROADCASTSD, BROADCASTSS, MOVDDUP, MOVSHDUP, MOVSLDUP, VMOVDDUP, VMOVSHDUP, and VMOVSLDUP.

yacc

yacc工具(go tool yacc)被移除了。在1.7版本,编译器不再使用。他被移出了工具库,现在位于地址=》https://godoc.org/golang.org/x/tools/cmd/goyacc

fix

fix工具有了一个新的修复,可以将“golang.org/x/net/context”改到“context”。

Pprof

pprof工具现在可以profile TLS服务器,并且通过使用”https+insecure”URL范式来跳过证书验证。 callgrind输出现在有了指令级别的粒度。

Trace

trace工具现在有了一个新的-pprof选项来产生pprof兼容的数据。 GC事件在执行追踪视图中更加清楚地展示了出来。GC活动在自己的行上展示,GC协程被他们自己的角色标注了。

Vet

Vet现在检查对锁数组的拷贝、重复的json、xml结构体字段tag,非空格分割的结构体tag,http请求体的关闭,Printf中使用的参数。

编译器工具链

Go1.7介绍了一个x86-64系统的新的编译器后端。在1.8中,这个后端更加精进,现在已经用于所有平台。 这个新的后端,基于SSA,生成更加压缩、高效的代码,并且提供了更好的平台优化,比如边界检查消除。这个新的后端在32位系统中可以减少性能测试时20%~30%的CPU需求。对于已经使用了1.7版本中SSA的64位x86系统,收益是0%~10%。其他平台的数据更接近于32位ARM。 在1.7中的-ssa=0临时选项在1.8中被移除了。 除了全平台支持新的编译器后端之外,Go1.8介绍了一个新的编译器前端。这个新的编译器前端对用户无感知,但是是未来性能优化工作的基础。 编译器和连接器优化过比Go1.7跑得更快,虽然仍然低于我们的预期,在未来会继续优化。相比于前一个版本,Go1.8大约快了15%。

Cgo

这个Go工具现在在make.bash时记住环境变量CGO_ENABLED,并将它应用到以后的编译中,以修复issue#12808。在做原生编译时,隐式设置CGO_ENABLED环境变量十分必要,因为make.bash会自动检查正确的设置。隐式设置CGO_ENABLED的主要原因是当你的环境支持时,但你不希望隐式使用cgo,可以在make.bash或all.bash时,设置CGO_ENABLED=0。 环境变量PKG_CONFIG现在可以用来直接配置cgo的包依赖(pkg-config)。pkg-config默认使用最早的releases。这是为了更方便的交叉编译cgo代码。 cgo工具现在支持一个-srcdir选项,这是一个过去用在go命令上的选项。 如果cgo代码调用了C.malloc,并且malloc返回了NULL,程序会返回一个oom错误并崩溃。C.malloc永远不会返回nil,不想其他C函数,C.malloc不应该使用多值返回来处理错误。 如果cgo传一个union指针来调用一个C函数,并且如果这个C union结构能包含任何指针值,并且如果允许cgo指针检查,这个union值现在当做Go指针来检查

Gccgo

因为Go半年发布一次,而GCC一年发布一次,所以GCC6包含了1.6.1版本的gccgo。我们希望GCC7能包含Go1.8版本的gccgo。

默认GOPATH

现在GOPATH有了一个默认值。默认指向 unix系统上为$HOME/go,windows系统上为%USERPROFILE%/go

Go get

HTTP代理环境变量现在能够一直对go get 命令生效,无论-insecure选项是否使用了。在之前的版本中,-insecure选项在没有设置代理时有副作用。

Go bug

新的go bug命令在github上生成一个bug报告,报告中预写了当前系统的信息。

Go doc

go doc命令现在通过类型将常量和变量分组,与godoc的行为一致 为了提升文档的可读性,所有第一层项目(the first-level items)的总结都保证独占一行。 interface定义中的指定方法,可以生成文档,比如”go doc net.Conn.SetDeadline”.

插件/补丁

Go现在支持“plugin”模式下的用Go写的插件,和一个新的plugin包用来在运行时加载。插件支持现在只在Linux平台上可用。请随时提交议题。

运行时

参数声明周期

gc不再认为参数的声明周期是贯穿整个函数的。更多信息,或学习如何使得变量存活,可以在1.7新增的runtime.KeepAlive方法中看到。 更新:对变量设置finalizer方法的对象现在可能需要增加runtime.KeepAlive方法的调用。阅读KeepAlive的文档获取更多细节。

Concurrent Map 误用

在Go1.6,运行时增加了轻量级、尽力尝试的对maps并发误用的检测。这个版本增加了检测器,支持对并发写和遍历的检测。 一如往常,如果一个协程正在对map写,其他协程都不应该读(包括遍历)或者并发写。如果运行时检查到了这个情况,就会打印出诊断信息并且引起崩溃。最好的发现这个问题的方法是在竞态检测下运行程序,可以更加可靠地证明竞争,以及给出更多细节。

MemStats文档

runtime.MemStats类型有了更加完善的文档。

性能

像之前一样,变化非常广泛和多元化,很难做出对性能的精确描述。大多数程序应该能够跑得更快一些,因为gc的提速和标准库的优化。 多个包的实现上都有优化,包括以下:

bytes, crypto/aes, crypto/cipher, crypto/elliptic, crypto/sha256, crypto/sha512, encoding/asn1, encoding/csv, encoding/hex, encoding/json, hash/crc32, image/color, image/draw, math, math/big, reflect, regexp, runtime, strconv, strings, syscall, text/template, unicode/utf8.

GC

GC停顿现在相比Go1.7应该显著缩短了,通常低于100微秒,并且经常低于10微妙。更多详情见关于淘汰stw栈重扫的文档。Go1.9会完成更多工作。

Defer

defer函数的调用开销减半了。

Cgo

从Go调用进C的开销减半。

标准库

例子

更多包的例子加进了文档。

排序

sort包现在包含了一个通用的函数Slice以排序一个slice以给定的函数。这意味着不再需要实现一个新的sorter类型。此外还有新的函数SliceStableSliceIsSorted

HTTP/2 Push

net/http包现在包含了发送HTTP/2从handler推送的机制。跟已存的Flusher和Hijacker接口类似,一个Http/2的ResponseWriter现在实现了新的Pusher接口。

HTTP Server Graceful Shutdown

HTTP Server现在支持用新的Server.Shutdown方法来支持graceful shutdown和新的Server.Close来突然关闭。

更多的Context支持

紧接着Go1.7将context.Context采纳进标准库,Go1.8增加了更多的支持到现存的包: 新的Server.Shutdown接受一个context参数。 database/sql包增加了很多对context的支持。 全部九个新的net.Resolver的lookup方法现在持有一个context.

Mutex Contention Profiling

现在运行时支持分析竞争互斥锁。 大多数用户会希望在使用go test时指定-mutexprofile选项,,并且在相关文件上使用pprof。 通过新的MutexProfileSetMutexProfileFraction可以实现更低层次的支持。 一个已知的Go1.8的局限是,这个profile只支持sync.Mutex而不支持sync.RWMutex

库的微小改动

像往常一样,在保证Go1.x兼容的情况下。对标准库做了诸多微小改动和更新。以下的章节罗列了用户可见的改动和增加。性能优化和bug修复没有再次列出。(译者注:详情不再列出了)