Go 1.13 发行说明
Go 1.13 简介
最新的 Go 版本 1.13 在 Go 1.12 发布六个月后推出。其大部分更改都在工具链、运行时和库的实现中。与往常一样,此版本维护了 Go 1 的 兼容性承诺。我们预计几乎所有 Go 程序都将像以前一样继续编译和运行。
从 Go 1.13 开始,go 命令默认使用 Google 运行的 Go 模块镜像和 Go 校验和数据库下载和验证模块。有关这些服务的隐私信息,请参阅 https://proxy.golang.org/privacy,有关配置详细信息(包括如何禁用这些服务器的使用或使用其他服务器),请参阅 go 命令文档。如果您依赖于非公共模块,请参阅 配置环境的文档。
语言更改
根据 数字字面量提案,Go 1.13 支持更统一且现代化的数字字面量前缀集。
- 二进制整数字面量:前缀
0b
或0B
表示二进制整数字面量,例如0b1011
。 - 八进制整数字面量:前缀
0o
或0O
表示八进制整数字面量,例如0o660
。由一个前导0
后跟八进制数字表示的现有八进制表示法仍然有效。 - 十六进制浮点字面量:现在可以使用前缀
0x
或0X
以十六进制格式表示浮点数的尾数,例如0x1.0p-1021
。十六进制浮点数必须始终具有指数,写成字母p
或P
后跟十进制指数。指数将尾数按 2 的指数次幂进行缩放。 - 虚数字面量:虚数后缀
i
现在可以与任何(二进制、十进制、十六进制)整数或浮点字面量一起使用。 - 数字分隔符:任何数字字面量的数字现在都可以使用下划线分隔(分组),例如
1_000_000
、0b_1010_0110
或3.1415_9265
。下划线可以出现在任意两个数字之间或字面量前缀和第一个数字之间。
根据 带符号移位计数提案,Go 1.13 删除了 移位计数 必须无符号的限制。此更改消除了许多人为 uint
转换的需要,这些转换仅仅是为了满足 <<
和 >>
运算符的(现已删除的)限制。
这些语言更改是通过对编译器进行更改以及对库包 go/scanner
和 text/scanner
(数字字面量)以及 go/types
(带符号移位计数)进行相应的内部更改来实现的。
如果您的代码使用模块并且您的 go.mod
文件指定了语言版本,请确保将其设置为至少 1.13
以访问这些语言更改。您可以直接编辑 go.mod
文件,也可以运行 go mod edit -go=1.13
。
端口
Go 1.13 是最后一个将在 Native Client (NaCl) 上运行的版本。
对于 GOARCH=wasm
,新的环境变量 GOWASM
采用逗号分隔的列表,其中包含二进制文件编译时使用的实验性功能。有效值记录 此处。
AIX
PPC64 上的 AIX (aix/ppc64
) 现在支持 cgo、外部链接以及 c-archive
和 pie
构建模式。
Android
Go 程序现在与 Android 10 兼容。
Darwin
如 Go 1.12 发行说明中 宣布的那样,Go 1.13 现在需要 macOS 10.11 El Capitan 或更高版本;对先前版本的支持已停止。
FreeBSD
如 Go 1.12 发行说明中 宣布的那样,Go 1.13 现在需要 FreeBSD 11.2 或更高版本;对先前版本的支持已停止。FreeBSD 12.0 或更高版本需要具有 COMPAT_FREEBSD11
选项集的内核(这是默认设置)。
Illumos
Go 现在使用 GOOS=illumos
支持 Illumos。illumos
构建标签暗示 solaris
构建标签。
Windows
内部链接的 Windows 二进制文件指定的 Windows 版本现在为 Windows 7 而不是 NT 4.0。这已经是 Go 的最低要求版本,但可能会影响具有向后兼容模式的系统调用的行为。这些现在将按文档记录的行为执行。外部链接的二进制文件(任何使用 cgo 的程序)始终指定了更新的 Windows 版本。
工具
模块
环境变量
GO111MODULE
环境变量继续默认为 auto
,但 auto
设置现在会在当前工作目录包含或位于包含 go.mod
文件的目录下时激活 go
命令的模块感知模式——即使当前目录位于 GOPATH/src
中也是如此。此更改简化了 GOPATH/src
中现有代码的迁移以及模块感知包与非模块感知导入程序并存的持续维护。
新的 GOPRIVATE
环境变量指示不可公开访问的模块路径。它用作较低级 GONOPROXY
和 GONOSUMDB
变量的默认值,这些变量提供更细粒度的控制,以控制哪些模块通过代理获取并使用校验和数据库进行验证。
GOPROXY
环境变量 现在可以设置为代理 URL 的逗号分隔列表或特殊标记 direct
,其 默认值 现在为 https://proxy.golang.org,direct
。当将包路径解析为其包含的模块时,go
命令将依次尝试列表中每个代理上的所有候选模块路径。无法访问的代理或 HTTP 状态代码(非 404 或 410)将终止搜索,而不会咨询其余代理。
新的 GOSUMDB
环境变量 标识要咨询的数据库的名称以及可选的公钥和服务器 URL,以获取尚未在主模块的 go.sum
文件中列出的模块的校验和。如果 GOSUMDB
不包含显式 URL,则通过探测 GOPROXY
URL 以查找指示对校验和数据库支持的端点来选择 URL,如果任何代理都不支持,则回退到与命名数据库的直接连接。如果 GOSUMDB
设置为 off
,则不会咨询校验和数据库,并且仅验证 go.sum
文件中现有的校验和。
无法访问默认代理和校验和数据库的用户(例如,由于防火墙或沙箱配置)可以通过将 GOPROXY
设置为 direct
和/或将 GOSUMDB
设置为 off
来禁用其使用。go
env
-w
可用于设置这些变量的默认值,而与平台无关
go env -w GOPROXY=direct
go env -w GOSUMDB=off
go
get
在模块感知模式下,带有 -u
标志的 go
get
现在更新一组较小的模块,这与 GOPATH 模式下 go
get
-u
更新的包集更加一致。go
get
-u
继续更新命令行上命名的模块和包,但此外仅更新包含被命名包导入的包的模块,而不是包含命名包的模块的传递模块需求。
特别要注意的是,go
get
-u
(无其他参数)现在仅更新当前目录中包的传递导入。要改为更新主模块传递导入的所有包(包括测试依赖项),请使用 go
get
-u
all
。
由于上述对 go
get
-u
的更改,go
get
子命令不再支持 -m
标志,该标志会导致 go
get
在加载包之前停止。-d
标志仍然受支持,并且继续导致 go
get
在下载构建命名包的依赖项所需的源代码后停止。
默认情况下,模块模式下的 go
get
-u
仅升级非测试依赖项,就像 GOPATH 模式一样。它现在还接受 -t
标志,该标志(如 GOPATH 模式)会导致 go
get
包括命令行上命名的包的测试导入的包。
在模块感知模式下,go
get
子命令现在支持版本后缀 @patch
。@patch
后缀指示应将命名模块或包含命名包的模块更新到与构建列表中找到的版本具有相同主版本和次版本号的最高补丁版本。
如果作为参数传递给 go
get
的模块没有版本后缀,并且已经需要比最新发布版本更新的版本,它将保留在更新的版本中。这与模块依赖项的 -u
标志的行为一致。这可以防止从预发布版本意外降级。新的版本后缀 @upgrade
明确请求此行为。@latest
明确请求最新版本,无论当前版本如何。
版本验证
从版本控制系统提取模块时,go
命令现在对请求的版本字符串执行其他验证。
+incompatible
版本注释绕过了 语义导入版本控制 的要求,适用于模块引入之前的存储库。go
命令现在会验证此类版本是否不包含显式的 go.mod
文件。
go
命令现在验证 伪版本 和版本控制元数据之间的映射。具体来说
- 版本前缀必须采用
vX.0.0
的形式,或者派生自命名修订版本祖先上的标签,或者派生自包含构建元数据的命名修订版本本身的标签。 - 日期字符串必须与修订版本的UTC时间戳匹配。
- 修订版本的短名称必须使用与
go
命令生成的字符数相同。(对于git
使用的SHA-1哈希,为12位前缀。)
如果主模块中的require
指令使用无效的伪版本,通常可以通过将版本缩减为仅提交哈希并重新运行go
命令(例如go
list
-m
all
或go
mod
tidy
)来更正。例如,
require github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c
可以缩减为
require github.com/docker/docker e7b5f7dbe98c
目前解析为
require github.com/docker/docker v0.7.3-0.20190319215453-e7b5f7dbe98c
如果主模块的传递依赖项之一需要无效的版本或伪版本,则可以使用replace
指令在主模块的go.mod
文件中将无效版本替换为有效版本。如果替换是提交哈希,它将如上所述解析为相应的伪版本。例如,
replace github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c => github.com/docker/docker e7b5f7dbe98c
目前解析为
replace github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c => github.com/docker/docker v0.7.3-0.20190319215453-e7b5f7dbe98c
Go命令
go
env
命令现在接受-w
标志来设置go
命令识别的环境变量的每个用户的默认值,以及相应的-u
标志来取消先前设置的默认值。通过go
env
-w
设置的默认值存储在os.UserConfigDir()
内的go/env
文件中。
go
version
命令现在接受命名可执行文件和目录的参数。当对可执行文件调用时,go
version
打印用于构建可执行文件的Go版本。如果使用了-m
标志,go
version
将打印可执行文件的嵌入式模块版本信息(如果可用)。当对目录调用时,go
version
打印有关该目录及其子目录中包含的可执行文件的信息。
新的go
build
标志 -trimpath
从已编译的可执行文件中删除所有文件系统路径,以提高构建的可重复性。
如果传递给go
build
的-o
标志引用的是现有目录,则go
build
现在将在该目录中为与包参数匹配的main
包写入可执行文件。
go
build
标志-tags
现在接受以逗号分隔的构建标签列表,以允许在GOFLAGS
中使用多个标签。以空格分隔的形式已弃用,但仍被识别并会继续维护。
go
generate
现在设置generate
构建标签,以便可以搜索指令但构建期间忽略文件。
如Go 1.12发行说明中宣布的那样,不再支持仅二进制文件包。构建仅二进制文件包(用//go:binary-only-package
注释标记)现在会导致错误。
编译器工具链
编译器具有新的逃逸分析实现,该实现更精确。对于大多数Go代码来说,这应该是一个改进(换句话说,更多Go变量和表达式分配在栈上而不是堆上)。但是,这种提高的精度也可能破坏以前碰巧有效的无效代码(例如,违反unsafe.Pointer
安全规则的代码)。如果您注意到任何似乎相关的回归,可以使用go
build
-gcflags=all=-newescape=false
重新启用旧的逃逸分析传递。在将来的版本中将删除使用旧逃逸分析的选项。
编译器不再将浮点数或复数常量输出到go_asm.h
文件中。这些始终以无法用作汇编代码中数字常量的方式输出。
汇编器
汇编器现在支持ARM v8.1中引入的许多原子指令。
gofmt
gofmt
(以及go fmt
)现在将数字文字前缀和指数规范化为使用小写字母,但保留十六进制数字。这在使用新的八进制前缀时提高了可读性(0O
变为0o
),并且重写被一致地应用。gofmt
现在还从十进制整数虚数文字中删除不必要的零前导。(为了向后兼容,以0
开头的整数虚数文字被视为十进制,而不是八进制数。删除多余的零前导可以避免潜在的混淆。)例如,0B1010
、0XabcDEF
、0O660
、1.2E3
和01i
在应用gofmt
后分别变为0b1010
、0xabcDEF
、0o660
、1.2e3
和1i
。
godoc
和go
doc
godoc
Web服务器不再包含在主二进制发行版中。要在本地运行godoc
Web服务器,请先手动安装它。
go get golang.org/x/tools/cmd/godoc
godoc
go
doc
命令现在始终在其输出中包含包子句,命令除外。这取代了以前使用启发式方法的行为,导致在某些条件下省略包子句。
运行时
超出范围的panic消息现在包含超出范围的索引以及切片的长度(或容量)。例如,在长度为1的切片上使用s[3]
将引发“runtime error: index out of range [3] with length 1”的panic。
此版本将大多数defer
用法的性能提高了30%。
运行时现在更积极地将内存返回给操作系统,使其可供共同租户应用程序使用。以前,运行时可以在堆大小激增后保留内存五分钟或更长时间。它现在将在堆缩小后立即开始返回内存。但是,在许多操作系统(包括Linux)上,操作系统本身会延迟回收内存,因此进程RSS不会减少,除非系统处于内存压力之下。
标准库
TLS 1.3
如Go 1.12中宣布的那样,Go 1.13默认情况下启用对crypto/tls
包中TLS 1.3的支持。可以通过将值tls13=0
添加到GODEBUG
环境变量来禁用它。在Go 1.14中将删除退出选项。
请参阅Go 1.12发行说明以获取重要的兼容性信息。
crypto/ed25519
新的crypto/ed25519
包实现了Ed25519签名方案。此功能以前由golang.org/x/crypto/ed25519
包提供,当与Go 1.13+一起使用时,该包成为crypto/ed25519
的包装器。
错误包装
Go 1.13包含对错误包装的支持,如错误值提案中首次提出的以及在相关问题上讨论的那样。
错误e
可以通过提供返回w
的Unwrap
方法来包装另一个错误w
。e
和w
都可供程序使用,允许e
为w
提供额外的上下文或重新解释它,同时仍然允许程序根据w
做出决策。
为了支持包装,fmt.Errorf
现在具有用于创建包装错误的%w
动词,以及errors
包中的三个新函数(errors.Unwrap
、errors.Is
和errors.As
)简化了包装错误的解包和检查。
有关更多信息,请阅读errors
包文档,或查看错误值常见问题解答。很快还将有一篇博文。
库的次要更改
与往常一样,库中存在各种次要更改和更新,这些更改和更新是在Go 1兼容性承诺的指导下进行的。
bytes
新的ToValidUTF8
函数返回给定字节切片的副本,其中每个无效UTF-8字节序列运行都被替换为给定的切片。
context
WithValue
返回的上下文的格式不再依赖于fmt
,并且不会以相同的方式进行字符串化。依赖于之前确切字符串化的代码可能会受到影响。
crypto/tls
对SSL版本3.0(SSLv3)的支持现已弃用,并将在Go 1.14中删除。请注意,SSLv3是早于TLS的加密已损坏的协议。
SSLv3始终默认禁用,除了在Go 1.12中,当时它在服务器端被错误地默认启用。它现在再次默认禁用。(SSLv3从未在客户端端支持。)
Ed25519证书现在在TLS版本1.2和1.3中受支持。
crypto/x509
Ed25519密钥现在在证书和证书请求中受支持,符合RFC 8410,以及ParsePKCS8PrivateKey
、MarshalPKCS8PrivateKey
和ParsePKIXPublicKey
函数。
搜索系统根的路径现在包括/etc/ssl/cert.pem
,以支持Alpine Linux 3.7+中的默认位置。
database/sql
新的NullTime
类型表示可能为null的time.Time
。
新的NullInt32
类型表示可能为null的int32
。
debug/dwarf
Data.Type
方法不再在类型图中遇到未知DWARF标签时引发panic。相反,它使用UnsupportedType
对象表示类型的该组件。
errors
新函数As
查找给定错误链(包装错误序列)中第一个与给定目标类型匹配的错误,如果匹配,则将目标设置为该错误值。
新函数Is
报告给定错误值是否与另一个错误链中的错误匹配。
新函数Unwrap
返回调用给定错误上的Unwrap
的结果(如果存在)。
fmt
打印动词%x
和%X
现在以十六进制表示法(分别为小写和大写)格式化浮点数和复数。
新的打印动词%O
以8为基数格式化整数,输出0o
前缀。
扫描程序现在接受十六进制浮点数、数字分隔的下划线以及前导0b
和0o
前缀。有关详细信息,请参阅语言更改。
Errorf
函数有一个新的动词%w
,其操作数必须是错误。从Errorf
返回的错误将具有一个Unwrap
方法,该方法返回%w
的操作数。
go/scanner
扫描程序已更新以识别新的Go数字文字,特别是带有0b
/0B
前缀的二进制文字、带有0o
/0O
前缀的八进制文字以及带有十六进制尾数的浮点数。虚数后缀i
现在可以与任何数字文字一起使用,并且下划线可以用作数字分隔符进行分组。有关详细信息,请参阅语言更改。
go/types
类型检查器已更新以遵循整数移位的规则。有关详细信息,请参阅语言更改。
html/template
当使用带有“module”作为类型属性的<script>
标签时,代码现在将被解释为JavaScript模块脚本。
log
新的Writer
函数返回标准记录器的输出目标。
math/big
新的Rat.SetUint64
方法将Rat
设置为uint64
值。
对于Float.Parse
,如果基数为0,则可以在数字之间使用下划线以提高可读性。有关详细信息,请参阅语言更改。
对于 Int.SetString
,如果基数为 0,则可以在数字之间使用下划线以提高可读性。有关详细信息,请参阅 语言更改。
Rat.SetString
现在接受非十进制浮点表示。
math/bits
Add
、Sub
、Mul
、RotateLeft
和 ReverseBytes
的执行时间现在保证与输入无关。
net
在 resolv.conf
中设置了 use-vc
的 Unix 系统上,使用 TCP 进行 DNS 解析。
新的字段 ListenConfig.KeepAlive
指定侦听器接受的网络连接的保持活动周期。如果此字段为 0(默认值),则将启用 TCP 保持活动。要禁用它们,请将其设置为负值。
请注意,从因保持活动超时而关闭的连接上的 I/O 返回的错误将具有一个 Timeout
方法,如果调用该方法,则该方法将返回 true
。这可能使保持活动错误难以与因 SetDeadline
方法和类似方法设置的截止时间未达到而返回的错误区分开来。使用截止时间并使用 Timeout
方法或 os.IsTimeout
检查截止时间的代码可能希望禁用保持活动,或使用 errors.Is(syscall.ETIMEDOUT)
(在 Unix 系统上),它将对保持活动超时返回 true,对截止时间超时返回 false。
net/http
新的字段 Transport.WriteBufferSize
和 Transport.ReadBufferSize
允许指定 Transport
的写入和读取缓冲区的大小。如果这两个字段均为零,则使用 4KB 的默认大小。
新的字段 Transport.ForceAttemptHTTP2
控制在提供非零 Dial
、DialTLS
或 DialContext
函数或 TLSClientConfig
时是否启用 HTTP/2。
Transport.MaxConnsPerHost
现在可以与 HTTP/2 正确配合使用。
TimeoutHandler
的 ResponseWriter
现在实现了 Pusher
接口。
已添加状态代码 103
"Early Hints"
。
Transport
现在使用 Request.Body
的 io.ReaderFrom
实现(如果可用),以优化主体写入。
在遇到不受支持的传输编码时,http.Server
现在返回“501 Unimplemented”状态,如 HTTP 规范 RFC 7230 第 3.3.1 节 所规定。
新的 Server
字段 BaseContext
和 ConnContext
允许更精细地控制提供给请求和连接的 Context
值。
http.DetectContentType
现在可以正确检测 RAR 签名,并且现在还可以检测 RAR v5 签名。
已添加一个新函数 NewRequestWithContext
,它接受一个 Context
,该上下文控制创建的传出 Request
的整个生命周期,适合与 Client.Do
和 Transport.RoundTrip
一起使用。
Transport
在服务器使用 "408 Request Timeout"
响应优雅地关闭空闲连接时不再记录错误。
os
新的 UserConfigDir
函数返回用于用户特定配置数据的默认目录。
如果使用 O_APPEND 标志打开 File
,则其 WriteAt
方法将始终返回错误。
os/exec
在 Windows 上,Cmd
的环境始终继承父进程的 %SYSTEMROOT%
值,除非 Cmd.Env
字段包含其显式值。
reflect
新的 Value.IsZero
方法报告 Value
是否为其类型的零值。
MakeFunc
函数现在允许对返回值进行赋值转换,而不是要求完全类型匹配。当返回的类型是接口类型,但实际返回的值是实现该类型的具体值时,这特别有用。
runtime
回溯、runtime.Caller
和 runtime.Callers
现在将初始化 PKG
的全局变量的函数称为 PKG.init
,而不是 PKG.init.ializers
。
strconv
对于 strconv.ParseFloat
、strconv.ParseInt
和 strconv.ParseUint
,如果基数为 0,则可以在数字之间使用下划线以提高可读性。有关详细信息,请参阅 语言更改。
strings
新的 ToValidUTF8
函数返回给定字符串的副本,其中每个无效 UTF-8 字节序列运行都替换为给定字符串。
sync
Mutex.Lock
、Mutex.Unlock
、RWMutex.Lock
、RWMutex.RUnlock
和 Once.Do
的快速路径现在已内联到其调用者中。对于 amd64 上的无竞争情况,这些更改使 Once.Do
的速度提高了两倍,并且 Mutex
/RWMutex
方法的速度提高了 10%。
大型 Pool
不再增加停止世界暂停时间。
Pool
不再需要在每次 GC 后完全重新填充。它现在跨 GC 保留一些对象,而不是释放所有对象,从而减少了 Pool
重度用户的负载峰值。
syscall
已从 Darwin 构建中删除了 _getdirentries64
的使用,以允许将 Go 二进制文件上传到 macOS App Store。
已在 SysProcAttr
中引入了新的 ProcessAttributes
和 ThreadAttributes
字段,用于 Windows,在创建新进程时公开安全设置。
在 Windows 上,零 Chmod
模式下不再返回 EINVAL
。
可以使用 errors.Is
将类型为 Errno
的值与 os
包中的错误值(如 ErrExist
)进行测试。
syscall/js
TypedArrayOf
已被 CopyBytesToGo
和 CopyBytesToJS
替换,用于在字节切片和 Uint8Array
之间复制字节。
testing
运行基准测试时,B.N
不再舍入。
新的方法 B.ReportMetric
允许用户报告自定义基准测试指标并覆盖内置指标。
测试标志现在注册在新的 Init
函数中,该函数由测试的生成 main
函数调用。因此,测试标志现在仅在运行测试二进制文件时才注册,并且在包初始化期间调用 flag.Parse
的包可能会导致测试失败。
text/scanner
扫描程序已更新为识别新的 Go 数字文字,特别是带有 0b
/0B
前缀的二进制文字、带有 0o
/0O
前缀的八进制文字以及带有十六进制尾数的浮点数。此外,新的 AllowDigitSeparators
模式允许数字文字包含下划线作为数字分隔符(默认情况下关闭以确保向后兼容)。有关详细信息,请参阅 语言更改。
text/template
新的 切片函数 返回通过以下参数对第一个参数进行切片的结果。
time
新的 Duration
方法 Microseconds
和 Milliseconds
将持续时间作为其各自命名单位的整数计数返回。
unicode
整个系统中的 unicode
包和相关支持已从 Unicode 10.0 升级到 Unicode 11.0,它添加了 684 个新字符,包括 7 个新脚本和 66 个新的表情符号。