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类型。此外还有新的函数SliceStable
和SliceIsSorted
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。
通过新的MutexProfile
和SetMutexProfileFraction
可以实现更低层次的支持。
一个已知的Go1.8的局限是,这个profile只支持sync.Mutex
而不支持sync.RWMutex
库的微小改动
像往常一样,在保证Go1.x兼容的情况下。对标准库做了诸多微小改动和更新。以下的章节罗列了用户可见的改动和增加。性能优化和bug修复没有再次列出。(译者注:详情不再列出了)