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(darwin/arm
端口)上 32 位二进制文件的 Go 版本。Go 继续支持 64 位 darwin/arm64
端口。
Windows
Windows 上的 Go 二进制文件现在已启用 DEP(数据执行保护)。
在 Windows 上,如果权限参数中未设置位 0o200
(所有者写入权限),则通过 os.OpenFile
使用 os.O_CREATE
标志或通过 syscall.Open
使用 syscall.O_CREAT
标志创建文件现在将以只读方式创建文件。这使得 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
运行时现在为 runtime.NumCPU
和 GOMAXPROCS
的默认值遵守区域 CPU 上限(zone.cpu-cap
资源控制)。
工具
Go 命令
Vendoring(供应商化)
当主模块包含顶级 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
现在可以在对性能敏感的代码中使用,而无需担心开销。
Goroutines 现在可以异步抢占。因此,不带函数调用的循环不再可能使调度程序死锁或显着延迟垃圾回收。这在所有平台(windows/arm
、darwin/arm
、js/wasm
和 plan9/*
除外)上都受支持。
抢占实现的一个结果是,在 Unix 系统(包括 Linux 和 macOS 系统)上,使用 Go 1.14 构建的程序将比使用早期版本构建的程序收到更多信号。这意味着使用 syscall
或 golang.org/x/sys/unix
等包的程序将看到更多慢速系统调用失败并出现 EINTR
错误。这些程序必须以某种方式处理这些错误,最可能是循环以再次尝试系统调用。有关此内容的更多信息,请参阅 Linux 系统的 man 7 signal
或其他系统的类似文档。
页分配器效率更高,并且在 GOMAXPROCS
值较高时,锁竞争显着减少。这在并行且高速进行的大量分配中表现为较低的延迟和较高的吞吐量。
内部计时器(由 time.After
、time.Tick
、net.Conn.SetDeadline
等使用)效率更高,锁竞争更少,上下文切换更少。这是一项性能改进,不应导致任何用户可见的更改。
编译器
此版本添加了 -d=checkptr
作为编译时选项,用于添加检测以动态检查 Go 代码是否遵循 unsafe.Pointer
安全规则。此选项默认启用(Windows 除外),带有 -race
或 -msan
标志,并可以通过 -gcflags=all=-d=checkptr=0
禁用。具体来说,-d=checkptr
检查以下内容
- 将
unsafe.Pointer
转换为*T
时,结果指针必须为T
适当地对齐。 - 如果指针算术的结果指向 Go 堆对象,则其中一个
unsafe.Pointer
类型的操作数必须指向同一对象。
目前不建议在 Windows 上使用 -d=checkptr
,因为它会在标准库中导致误报。
编译器现在可以使用 -json
标志输出关键优化的机器可读日志,包括内联、逃逸分析、边界检查消除和 nil 检查消除。
详细的逃逸分析诊断(-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.GetConfigForClient
,则 Config.Certificates
和 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 节添加到 DWARF Data
中。
新方法 (*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
包现在支持 freebsd/amd64
。
reflect
StructOf
现在支持通过设置 StructField
元素中的 PkgPath
字段来创建具有未导出字段的结构类型。
runtime
runtime.Goexit
不能再被递归的 panic
/recover
中止。
在 macOS 上,SIGPIPE
不再转发给 Go 运行时初始化之前安装的信号处理程序。这是必要的,因为 macOS 将 SIGPIPE
发送到主线程而不是写入关闭管道的线程。
runtime/pprof
生成的配置文件不再包含用于内联标记的伪 PC。内联函数的符号信息以 pprof 工具期望的格式编码。这是对最近版本中引入的回归的修复。
strconv
NumError
类型现在有一个 Unwrap
方法,可用于检索转换失败的原因。这支持使用 errors.Is
使用 NumError
值来查看底层错误是否为 strconv.ErrRange
或 strconv.ErrSyntax
。
sync
解锁高度争用的 Mutex
现在会直接将 CPU 让给下一个等待该 Mutex
的 goroutine。这显着提高了高 CPU 计数机器上高度争用的互斥锁的性能。
testing
testing 包现在支持 cleanup 函数,在测试或基准测试完成后调用,分别通过调用 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 个新字符,包括四个新脚本和 61 个新表情符号。