Go 1.14 发布说明
Go 1.14 简介
最新的 Go 版本 1.14 在 Go 1.13 发布六个月后发布。其大部分更改都体现在工具链、运行时和库的实现中。与往常一样,此版本保持了 Go 1 兼容性承诺。我们预计几乎所有 Go 程序都将像以前一样继续编译和运行。
go
命令中的模块支持现已准备好投入生产使用,我们鼓励所有用户迁移到 Go 模块以进行依赖项管理。如果您由于 Go 工具链中的问题而无法迁移,请确保已为此问题提交了开放性问题。(如果问题不在 Go1.15
里程碑中,请告诉我们它为什么阻止您迁移,以便我们适当地对其进行优先排序。)
语言更改
根据重叠接口提案,Go 1.14 现在允许嵌入具有重叠方法集的接口:嵌入接口中的方法可以具有与已存在于(嵌入)接口中的方法相同的名称和相同的签名。这解决了通常(但并非唯一)在菱形嵌入图中出现的问题。与以前一样,接口中显式声明的方法必须保持唯一。
端口
Darwin
Go 1.14 是最后一个将在 macOS 10.11 El Capitan 上运行的版本。Go 1.15 将需要 macOS 10.12 Sierra 或更高版本。
Go 1.14 是最后一个支持 macOS 上 32 位二进制文件(darwin/386
端口)的 Go 版本。从 macOS 10.15(Catalina)开始,macOS 不再支持它们。Go 继续支持 64 位 darwin/amd64
端口。
Go 1.14 可能是最后一个支持 iOS、iPadOS、watchOS 和 tvOS 上 32 位二进制文件(darwin/arm
端口)的 Go 版本。Go 继续支持 64 位 darwin/arm64
端口。
Windows
Windows 上的 Go 二进制文件现在已启用DEP(数据执行保护)。
在 Windows 上,通过 os.OpenFile
使用 os.O_CREATE
标志创建文件,或通过 syscall.Open
使用 syscall.O_CREAT
标志创建文件,如果权限参数中未设置位 0o200
(所有者写入权限),则现在将以只读方式创建该文件。这使得 Windows 上的行为更类似于 Unix 系统上的行为。
WebAssembly
现在可以通过 js.Value
对象从 Go 引用的 JavaScript 值进行垃圾回收。
js.Value
值不能再使用 ==
运算符进行比较,而必须使用其 Equal
方法进行比较。
js.Value
现在具有 IsUndefined
、IsNull
和 IsNaN
方法。
RISC-V
Go 1.14 包含对 Linux 上 64 位 RISC-V 的实验性支持(GOOS=linux
、GOARCH=riscv64
)。请注意,性能、汇编语法稳定性以及可能存在的正确性仍在开发中。
FreeBSD
Go 现在支持 FreeBSD 12.0 或更高版本上的 64 位 ARM 架构(freebsd/arm64
端口)。
Native Client (NaCl)
如 Go 1.13 发布说明中所述,Go 1.14 停止支持 Native Client 平台(GOOS=nacl
)。
Illumos
运行时现在会尊重区域 CPU 上限(zone.cpu-cap
资源控制)以用于 runtime.NumCPU
和 GOMAXPROCS
的默认值。
工具
Go 命令
供应商
当主模块包含顶级 vendor
目录并且其 go.mod
文件指定 go
1.14
或更高版本时,go
命令现在默认为 -mod=vendor
用于接受该标志的操作。该标志的一个新值 -mod=mod
使 go
命令改为从模块缓存加载模块(就像不存在 vendor
目录时一样)。
当设置 -mod=vendor
(显式或默认)时,go
命令现在会验证主模块的 vendor/modules.txt
文件与其 go.mod
文件是否一致。
go
list
-m
不再静默省略不在 vendor
目录中提供软件包的传递依赖项。如果设置了 -mod=vendor
并请求了未在 vendor/modules.txt
中提及的模块的信息,则现在会明确失败。
标志
go
get
命令不再接受 -mod
标志。以前,该标志的设置要么被忽略,要么导致构建失败。
当 go.mod
文件为只读且不存在顶级 vendor
目录时,现在默认设置 -mod=readonly
。
-modcacherw
是一个新标志,它指示 go
命令将模块缓存中新创建的目录保留在其默认权限下,而不是将其设为只读。使用此标志会更有可能导致测试或其他工具意外添加未包含在模块已验证校验和中的文件。但是,它允许使用 rm
-rf
(而不是 go
clean
-modcache
)来删除模块缓存。
-modfile=file
是一个新标志,它指示 go
命令读取(并可能写入)备用 go.mod
文件,而不是模块根目录中的文件。必须在模块根目录中存在名为 go.mod
的文件才能确定模块根目录,但不会访问它。当指定 -modfile
时,还会使用备用 go.sum
文件:其路径是从 -modfile
标志派生,方法是修剪 .mod
扩展名并附加 .sum
。
环境变量
GOINSECURE
是一个新环境变量,它指示 go
命令在直接从其源获取某些模块时,不要求 HTTPS 连接,并跳过证书验证。与现有的 GOPRIVATE
变量类似,GOINSECURE
的值是逗号分隔的 glob 模式列表。
模块外部的命令
当显式启用模块感知模式(通过设置 GO111MODULE=on
)时,如果不存在 go.mod
文件,则大多数模块命令的功能将更加有限。例如,go
build
、go
run
和其他构建命令只能构建标准库中的软件包以及命令行上指定为 .go
文件的软件包。
以前,go
命令会将每个软件包路径解析到模块的最新版本,但不会记录模块路径或版本。这导致了缓慢且不可重现的构建。
go
get
继续像以前一样工作,go
mod
download
和 go
list
-m
以及显式版本也是如此。
+incompatible
版本
如果模块的最新版本包含 go.mod
文件,则 go
get
将不再升级到该模块的不兼容主版本,除非显式请求此类版本或已要求此类版本。go
list
在直接从版本控制获取此类模块时也会省略不兼容的主版本,但如果代理报告则可能会包含它们。
go.mod
文件维护
除了 go
mod
tidy
之外的 go
命令不再删除指定间接依赖项版本的 require
指令,该指令已由主模块的其他(传递)依赖项隐含。
除了 go
mod
tidy
之外的 go
命令如果更改只是修饰性的,则不再编辑 go.mod
文件。
当设置 -mod=readonly
时,go
命令将不再因缺少 go
指令或错误的 // indirect
注释而失败。
模块下载
go
命令现在支持模块模式下的 Subversion 存储库。
go
命令现在包括来自模块代理和其他 HTTP 服务器的纯文本错误消息的片段。仅当错误消息是有效的 UTF-8 并且仅由图形字符和空格组成时,才会显示错误消息。
测试
go test -v
现在会根据实际情况流式传输 t.Log
输出,而不是在所有测试结束时流式传输。
运行时
此版本提高了大多数 defer
用法的性能,与直接调用延迟函数相比,几乎不会产生任何开销。因此,现在可以在性能关键型代码中使用 defer
,而无需担心开销问题。
Goroutine 现在是异步可抢占的。因此,没有函数调用的循环不再可能使调度程序死锁或显着延迟垃圾回收。这在除 windows/arm
、darwin/arm
、js/wasm
和 plan9/*
之外的所有平台上都受支持。
抢占实现的一个结果是,在包括 Linux 和 macOS 系统在内的 Unix 系统上,使用 Go 1.14 构建的程序将比使用早期版本构建的程序接收更多信号。这意味着使用诸如 syscall
或 golang.org/x/sys/unix
之类的软件包的程序将看到更多缓慢的系统调用以 EINTR
错误失败。这些程序将必须以某种方式处理这些错误,最有可能循环以再次尝试系统调用。有关此的更多信息,请参阅 Linux 系统的man 7 signal
或其他系统的类似文档。
页面分配器效率更高,并且在 GOMAXPROCS
的高值下产生的锁争用明显减少。这在并行且高速率执行的大量分配的更低延迟和更高吞吐量方面最为明显。
由 time.After
、time.Tick
、net.Conn.SetDeadline
及其相关函数使用的内部计时器效率更高,锁争用更少,上下文切换更少。这是一项性能改进,不应导致任何用户可见的更改。
编译器
此版本添加了-d=checkptr
作为编译时选项,用于添加检测代码是否遵循unsafe.Pointer
安全规则的检测机制。此选项在默认情况下启用(Windows 除外),在使用-race
或-msan
标志时启用,并可以通过-gcflags=all=-d=checkptr=0
禁用。具体来说,-d=checkptr
检查以下内容
- 将
unsafe.Pointer
转换为*T
时,生成的指针必须与T
正确对齐。 - 如果指针运算的结果指向一个Go堆对象,则其中一个
unsafe.Pointer
类型的操作数必须指向同一个对象。
目前不建议在 Windows 上使用-d=checkptr
,因为它会导致标准库出现错误警报。
编译器现在可以使用-json
标志输出关键优化的机器可读日志,包括内联、逃逸分析、边界检查消除和空检查消除。
详细的逃逸分析诊断(-m=2
)现在再次可用。这在先前版本中新的逃逸分析实现中被删除了。
macOS 二进制文件中的所有 Go 符号现在都以下划线开头,遵循平台约定。
此版本包含对编译器插入的模糊测试覆盖率检测的实验性支持。有关更多详细信息,请参阅问题 14565。此 API 可能会在将来的版本中更改。
边界检查消除现在使用切片创建的信息,并且可以消除类型小于int
的索引的检查。
标准库
新的字节序列哈希包
Go 1.14 包含一个新的包,hash/maphash
,它提供字节序列上的哈希函数。这些哈希函数旨在用于实现哈希表或其他需要将任意字符串或字节序列映射到无符号 64 位整数上的均匀分布的数据结构。
哈希函数具有抗碰撞性,但不是加密安全的。
给定字节序列的哈希值在单个进程中保持一致,但在不同的进程中将不同。
库的次要更改
与往常一样,对库进行了各种细微的更改和更新,并牢记 Go 1 的兼容性承诺。
crypto/tls
已删除对 SSL 版本 3.0 (SSLv3) 的支持。请注意,SSLv3 是在 TLS 之前就已经被证明存在加密漏洞的协议。
TLS 1.3 无法再通过GODEBUG
环境变量禁用。使用Config.MaxVersion
字段配置 TLS 版本。
当通过Config.Certificates
字段提供多个证书链时,现在会自动选择第一个与对等方兼容的证书。例如,这允许提供 ECDSA 和 RSA 证书,并让包自动选择最佳证书。请注意,除非设置了Certificate.Leaf
字段,否则此选择的性能会很差。Config.NameToCertificate
字段仅支持将单个证书与给定名称关联,现在已弃用,应将其保留为nil
。类似地,Config.BuildNameToCertificate
方法从叶子证书构建NameToCertificate
字段,现在已弃用,不应调用。
新的CipherSuites
和InsecureCipherSuites
函数返回当前已实现的密码套件列表。新的CipherSuiteName
函数返回密码套件 ID 的名称。
新的 (*ClientHelloInfo).SupportsCertificate
和 (*CertificateRequestInfo).SupportsCertificate
方法公开对等方是否支持某个证书。
tls
包不再支持旧的下一协议协商(NPN)扩展,现在仅支持 ALPN。在以前的版本中,它同时支持两者。没有 API 更改,应用程序应该像以前一样工作。大多数其他客户端和服务器已经删除了对 NPN 的支持,转而支持标准化的 ALPN。
在 TLS 1.2 握手时,现在使用 RSA-PSS 签名(如果支持)。这不会影响大多数应用程序,但那些不支持 RSA-PSS 签名的自定义Certificate.PrivateKey
实现将需要使用新的 Certificate.SupportedSignatureAlgorithms
字段来禁用它们。
Config.Certificates
和Config.GetCertificate
现在如果设置了Config.GetConfigForClient
,则都可以为 nil。如果回调既不返回证书也不返回错误,则现在发送unrecognized_name
。
新的CertificateRequestInfo.Version
字段向客户端证书回调提供 TLS 版本。
新的TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
和TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
常量使用先前称为TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
和TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
的密码套件的最终名称。
crypto/x509
Certificate.CreateCRL
现在支持 Ed25519 发行者。
debug/dwarf
debug/dwarf
包现在支持读取 DWARF 版本 5。
新方法(*Data).AddSection
支持从输入文件向 DWARF Data
添加任意新的 DWARF 部分。
新方法(*Reader).ByteOrder
返回当前编译单元的字节顺序。这可以用于解释以原生顺序编码的属性,例如位置描述。
新方法(*LineReader).Files
从行读取器返回文件名表。这可以用于解释 DWARF 属性(如AttrDeclFile
)的值。
encoding/asn1
Unmarshal
现在支持 ASN.1 字符串类型 BMPString,由新的TagBMPString
常量表示。
encoding/json
Decoder
类型支持一个新方法InputOffset
,它返回当前解码器位置的输入流字节偏移量。
Compact
不再转义U+2028
和U+2029
字符,这从来都不是一个记录的功能。对于正确的转义,请参阅HTMLEscape
。
Number
不再接受无效数字,以更紧密地遵循记录的行为。如果程序需要接受像空字符串这样的无效数字,请考虑使用Unmarshaler
包装类型。
Unmarshal
现在可以支持具有字符串底层类型的映射键,这些键实现了encoding.TextUnmarshaler
。
go/build
Context
类型有一个新的字段Dir
,可用于设置构建的工作目录。默认值为正在运行的进程的当前目录。在模块模式下,这用于定位主模块。
go/doc
新函数NewFromFiles
从*ast.File
列表计算包文档,并将示例与相应的包元素关联。新信息可在Package
、Type
和Func
类型中的新Examples
字段以及Example
类型中的新Suffix
字段中获得。
io/ioutil
TempDir
现在可以创建名称具有可预测前缀和后缀的目录。与TempFile
一样,如果模式包含“*”,则随机字符串将替换最后一个“*”。
log
新的Lmsgprefix
标志可用于指示日志函数在日志消息之前立即发出可选的输出前缀,而不是在行的开头。
math
新函数FMA
计算浮点数中的x*y+z
,不会对x*y
计算进行中间舍入。一些架构使用专用的硬件指令实现此计算,以提高性能。
math/big
GCD
方法现在允许输入a
和b
为零或负数。
math/bits
新函数Rem
、Rem32
和Rem64
支持即使在商溢出时计算余数。
mime
.js
和.mjs
文件的默认类型现在为text/javascript
,而不是application/javascript
。这符合IETF 草案,该草案将application/javascript
视为已过时。
mime/multipart
新Reader
方法NextRawPart
支持获取下一个 MIME 部分,而无需透明地解码quoted-printable
数据。
net/http
新的Header
方法Values
可用于获取与规范化键关联的所有值。
新的Transport
字段DialTLSContext
可用于指定用于为非代理 HTTPS 请求创建 TLS 连接的可选拨号函数。此新字段可以代替DialTLS
,后者现在被认为已弃用;DialTLS
将继续工作,但新代码应使用DialTLSContext
,它允许传输在不再需要时立即取消拨号。
在 Windows 上,ServeFile
现在可以正确地服务大于 2GB 的文件。
net/http/httptest
新的Server
字段EnableHTTP2
支持在测试服务器上启用 HTTP/2。
net/textproto
新的MIMEHeader
方法Values
可用于获取与规范化键关联的所有值。
net/url
当 URL 解析失败时(例如,由Parse
或ParseRequestURI
导致),生成的Error
消息现在将引用无法解析的 URL。这提供了更清晰的结构并与其他解析错误保持一致。
os/signal
在 Windows 上,CTRL_CLOSE_EVENT
、CTRL_LOGOFF_EVENT
和CTRL_SHUTDOWN_EVENT
事件现在会生成syscall.SIGTERM
信号,类似于 Control-C 和 Control-Break 如何生成syscall.SIGINT
信号。
plugin
plugin
包现在支持freebsd/amd64
。
reflect
StructOf
现在支持通过在StructField
元素中设置PkgPath
字段来创建具有未导出字段的结构体类型。
runtime
runtime.Goexit
不再能够被递归的panic
/recover
中止。
在 macOS 上,SIGPIPE
不再转发到在 Go 运行时初始化之前安装的信号处理程序。这是必要的,因为 macOS 会将SIGPIPE
传递给主线程,而不是写入已关闭管道的线程。
runtime/pprof
生成的配置文件不再包含用于内联标记的伪 PC。内联函数的符号信息以pprof 工具期望的格式进行编码。这是对最近版本中引入的回归的修复。
strconv
NumError
类型现在有一个 Unwrap
方法,可用于检索转换失败的原因。这支持将 NumError
值与 errors.Is
一起使用,以查看基础错误是否为 strconv.ErrRange
或 strconv.ErrSyntax
。
sync
解锁竞争激烈的 Mutex
现在会直接将 CPU 让给等待该 Mutex
的下一个 goroutine。这显著提高了在 CPU 核心数量多的机器上竞争激烈的互斥锁的性能。
testing
testing 包现在支持清理函数,在测试或基准测试完成后调用,分别通过调用 T.Cleanup
或 B.Cleanup
。
text/template
text/template 包现在在使用带括号的参数作为函数时会正确报告错误。这最常出现在类似 {{if (eq .F "a") or (eq .F "b")}}
的错误情况下。这应该写成 {{if or (eq .F "a") (eq .F "b")}}
。错误的情况从未按预期工作,现在将报告错误 can't give argument to non-function
。
JSEscape
现在对 &
和 =
字符进行转义,以减轻其输出在 HTML 上下文中被误用的影响。
unicode
整个系统中的 unicode
包和相关支持已从 Unicode 11.0 升级到 Unicode 12.0,增加了 554 个新字符,包括 4 种新的文字系统和 61 个新的表情符号。