Go1.12版本简介
最新的Go版本1.12在Go 1.11之后6个月后发布。它的大多数更新都在工具链、运行时和库的实现中。一如既往,该版本维护了Go 1的兼容性承诺。希望所有Go程序都能像以前一样继续编译和运行。
语言规范方面
语言规范没有更改。
平台
linux/arm64现在支持race检测器。Go 1.12是FreeBSD 10.x上支持的最后一个版本。Go 1.13将需要FreeBSD 11.2+或FreeBSD 12.0+。FreeBSD 12.0+要求内核设置COMPAT_FREEBSD11选项(这是默认设置)。现在linux/ppc64支持cgo。hurd在GOOS上的价值已经得到认可,将与gccgo一起保留给GNU/ hurd系统使用。
Windows
支持在32位arm芯片(如Raspberry Pi 3)的windows 10 IoT内核上运行Go。
AIX
Go1.12支持AIX 7.2以及POWER8体系结构(AIX /ppc64)上的更高版本。暂时还不支持外部链接、cgo、pprof和race检测器。
Darwin
Go 1.12将是macOS 10.10 Yosemite上运行的最后一个版本。Go 1.13将需要macOS 10.11 El Capitan或更高版本。在Darwin上进行系统调用时,现在使用libSystem,以确保与未来版本的macOS和iOS的向前兼容性。切换到libSystem将触发对私有API的额外应用程序商店检查。因为它是私有的,在iOS上syscall.Getdirentries将调用失败。
工具
Go
govet命令已被重写以作为一系列不同源代码分析工具的基础。有关详细信息,请参见golang.org/x/tools/go/analysis包。一个副作用是go tool vet不再受支持。使用go tool vet的外部工具必须更改为使用go vet。作为这个更新的一部分,实验性的 -shadow选项在go vet中不再支持。检查变量阴影现在可以使用:
go get -u golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
go vet -vettool=$(which shadow)
Tour
Go tour不再包含在主要的二进制发行版中。若要在本地运行tour,请手动安装,而不是运行go tool tour:
go get -u golang.org/x/tour
tour
建立缓存需求
现在需要构建缓存来消除$GOPATH/pkg。设置环境变量GOCACHE=off将导致写入缓存的go命令失败。
二进制包
Go 1.12是最后一个支持二进制包的版本。
Cgo
Go 1.12将把C类型的EGLDisplay转换为Go类型的uintptr。这种变化类似于Go 1.10和更新版本对Darwin的CoreFoundation和Java的JNI类型的处理。有关更多信息,请参阅cgo文档。在使用Cgo的包中,已损坏的C名称不再被接受,将使用Cgo名称代替。例如,使用文档化的cgo名称C.char,而不是_Ctype_char。
模块化
当GO111MODULE设置为on时,go命令现在支持模块目录之外的模块感知操作,只要这些操作不需要解析相对于当前目录的导入路径或显式编辑go.mod文件。go get、go list和go mod download等命令的行为就像在一个初始为空的模块中一样。此外,现在可以安全地并发调用下载和提取模块的go命令。模块缓存(GOPATH/pkg/mod)必须驻留在支持文件锁定的文件系统中。
go.mod文件中的go指令现在能指示该模块中文件使用的语言的版本。如果没有现有版本,它将被设置为当前版本(go 1.12)。如果模块的go指令指定了比正在使用的工具链更新的版本,go命令将尝试构建包,并且只在构建失败时才会注意到不匹配。
当无法使用活动模块解析导入时,go命令现在将尝试使用主模块的replace指令中提到的模块,然后再查询模块缓存和通常的网络源。如果找到匹配的,但是replace指令没有指定版本,go命令将使用从time.Time派生的伪版本(如v0.0.0-00010101000000-000000000000)。
编译器工具链
编译器的动态变量分析得到了改进。这意味着在这个版本中执行终结器(finalizer)时间要比在以前的版本中更快。如果对应用系统有影响,可以考虑适当地调用runtime.KeepAlive。默认情况下,现在有更多的函数可以内联,包括调用另一个函数的函数。这种额外的内联使得使用runtime.CallersFrames更重要而不是遍历runtime.Callers的结果。
// 不再正确工作的旧代码(它将无法使用内联调用帧)
var pcs [10]uintptr
n := runtime.Callers(1, pcs[:])
for _, pc := range pcs[:n] {
f := runtime.FuncForPC(pc)
if f != nil {
fmt.Println(f.Name())
}
}
// 将正确工作的新代码
var pcs [10]uintptr
n := runtime.Callers(1, pcs[:])
frames := runtime.CallersFrames(pcs[:n])
for {
frame, more := frames.Next()
fmt.Println(frame.Function)
if !more {
break
}
}
编译器生成包装器的实现方法不再由runtime. CallersFrames和runtime.Stack报告。它们也不会打印在panic堆栈跟踪中。此更新将gc工具链匹配gccgo工具链,gccgo工具链已经从堆栈跟踪中删除了此类包装器。这些api的客户机可能需要根据实际情况进行调整。
编译器现在接受-lang标志来设置要使用的Go语言版本。例如,如果程序使用Go 1.9中添加的类型别名,-lang=go1.8会导致编译器发出错误。在Go 1.12之前所做的语言更改并不是始终强制执行的。
编译器工具链现在使用不同的约定来调用Go函数和汇编函数,这对用户来说是透明的,除了同时跨Go和汇编以及跨包边界的调用。如果出现如ABIInternal相关错误,请参阅ABI设计文档的兼容性部分。
对编译器生成的DWARF调试信息进行了许多改进,包括对参数打印和变量位置信息的改进。
Go程序现在还在linux/arm64上维护堆栈帧指针,以便使用perf等分析工具。帧指针维护的运行时开销很小,平均在3%左右。要构建不使用框架指针的工具链,请在运行make.bash时设置GOEXPERIMENT=noframepointer。对于过时的“安全”编译器模式(由-u gcflag启用)已经被删除。
godoc
在go1.12中,godoc不再具有命令行界面,而只是一个web服务器。用户应该将go doc用于命令行帮助输出。Go 1.12是最后一个包含godoc web服务器的版本;在Go 1.13中,它将通过Go get提供。
godoc现在支持-all标志,这将导致它打印所有导出的API及其文档,就像godoc命令行过去所做的那样。go doc现在还包括-src标志,它将显示目标的源代码。
Trace工具
跟踪工具现在支持绘制mutator曲线,包括对执行跟踪的交叉引用。这对于分析垃圾收集器对应用程序延迟和吞吐量的影响非常有用。
汇编
在arm64上,平台寄存器从R18重命名为R18_PLATFORM,以防止意外误用。
运行时
Go1.12显著提高了在堆中垃圾回收的性能,减少了垃圾收集之后的分配延迟。Go运行时现在更积极地将内存释放回操作系统,特别是在无法重用现有堆空间的大内存分配时。
Go运行时的计时器和截止日代码更快,并且在cpu数量较高的情况下伸缩性更好。特别是,这提高了操作网络连接截止日期的性能。
在Linux上,运行时现在使用MADV_FREE释放未使用的内存。这更有效,但可能导致更高的RSS。内核将在需要时回收未使用的数据。要恢复到Go1.11的方式(MADV_DONTNEED),可以通过设置环境变量GODEBUG=madvdontneed=1。
添加cpu.extension=off到GODEBUG环境变量,可以禁止在标准库和运行时中使用可选的CPU指令集扩展。这在Windows上还不支持。Go1.12通过修复大堆分配的过度计数,提高了内存配置文件的准确性。回溯runtime.Caller和runtime.Callers将不再包含编译器生成的初始化函数。在全局变量初始化期间执行回溯,现在将显示名为PKG.init.ializer的函数。
核心库
TLS 1.3
Go1.12在RFC8446指定的crypto/TLS包中添加了对TLS1.3的可选支持。可以通过将tls13=1值添加到GODEBUG环境变量中来启用它。在Go1.13中默认启用。要使用TLS1.3,请确保没有在Config中设置显式的MaxVersion,并在环境变量中设置GODEBUG=tls13=1。
大部分TLS1.2的所有特性在TLS1.3中都可用,并提供同等或更好的安全性和性能。请注意,尽管TLS1.3向后兼容以前的版本,但某些遗留系统可能无法正常工作。RSA证书密钥太小而不安全(包括512位密钥)将不能用于TLS1.3。
TLS1.3密码套件是不可配置的。所有支持的密码套件都是安全的,如果在配置中设置了PreferServerCipherSuites,那么首选项顺序将基于可用的硬件。
早期数据(也称为“0-RTT模式”)目前不支持作为客户机或服务器。由于TLS1.3 0-RTT模式涉及到客户端哪些服务器支持0-RTT的状态,所以Go1.12服务器不能成为负载平衡池的一部分。如果将一个域从支持0-RTT的服务器切换到Go1.12服务器,则在切换之前必须禁用0-RTT。
在TLS 1.3中,客户机在握手过程中最后发送消息,因此如果它导致服务器上发生错误,那么它将通过第一次读取(而不是握手)在客户机上返回。例如,如果服务器拒绝客户端证书,就会出现这种情况。类似地,session会话凭证现在是握手后的消息,因此只在客户机第一次读取时接收session会话凭证。
版权声明:本文版权归作者(译者)所有,欢迎转载,但未经作者(译者)同意必须保留此段声明,且在文章页面明显位置给出,本文链接如有问题,可留言咨询。