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 支持更统一且现代化的数字字面量前缀集。

根据 带符号移位计数提案,Go 1.13 删除了 移位计数 必须无符号的限制。此更改消除了许多人为 uint 转换的需要,这些转换仅仅是为了满足 <<>> 运算符的(现已删除的)限制。

这些语言更改是通过对编译器进行更改以及对库包 go/scannertext/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-archivepie 构建模式。

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 环境变量指示不可公开访问的模块路径。它用作较低级 GONOPROXYGONOSUMDB 变量的默认值,这些变量提供更细粒度的控制,以控制哪些模块通过代理获取并使用校验和数据库进行验证。

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 命令现在验证 伪版本 和版本控制元数据之间的映射。具体来说

如果主模块中的require指令使用无效的伪版本,通常可以通过将版本缩减为仅提交哈希并重新运行go命令(例如go list -m allgo 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开头的整数虚数文字被视为十进制,而不是八进制数。删除多余的零前导可以避免潜在的混淆。)例如,0B10100XabcDEF0O6601.2E301i在应用gofmt后分别变为0b10100xabcDEF0o6601.2e31i

godocgo 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可以通过提供返回wUnwrap方法来包装另一个错误wew都可供程序使用,允许ew提供额外的上下文或重新解释它,同时仍然允许程序根据w做出决策。

为了支持包装,fmt.Errorf现在具有用于创建包装错误的%w动词,以及errors包中的三个新函数(errors.Unwraperrors.Iserrors.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,以及ParsePKCS8PrivateKeyMarshalPKCS8PrivateKeyParsePKIXPublicKey函数。

搜索系统根的路径现在包括/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前缀。

扫描程序现在接受十六进制浮点数、数字分隔的下划线以及前导0b0o前缀。有关详细信息,请参阅语言更改

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

AddSubMulRotateLeftReverseBytes 的执行时间现在保证与输入无关。

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.WriteBufferSizeTransport.ReadBufferSize 允许指定 Transport 的写入和读取缓冲区的大小。如果这两个字段均为零,则使用 4KB 的默认大小。

新的字段 Transport.ForceAttemptHTTP2 控制在提供非零 DialDialTLSDialContext 函数或 TLSClientConfig 时是否启用 HTTP/2。

Transport.MaxConnsPerHost 现在可以与 HTTP/2 正确配合使用。

TimeoutHandlerResponseWriter 现在实现了 Pusher 接口。

已添加状态代码 103 "Early Hints"

Transport 现在使用 Request.Bodyio.ReaderFrom 实现(如果可用),以优化主体写入。

在遇到不受支持的传输编码时,http.Server 现在返回“501 Unimplemented”状态,如 HTTP 规范 RFC 7230 第 3.3.1 节 所规定。

新的 Server 字段 BaseContextConnContext 允许更精细地控制提供给请求和连接的 Context 值。

http.DetectContentType 现在可以正确检测 RAR 签名,并且现在还可以检测 RAR v5 签名。

新的 Header 方法 Clone 返回接收者的副本。

已添加一个新函数 NewRequestWithContext,它接受一个 Context,该上下文控制创建的传出 Request 的整个生命周期,适合与 Client.DoTransport.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.Callerruntime.Callers 现在将初始化 PKG 的全局变量的函数称为 PKG.init,而不是 PKG.init.ializers

strconv

对于 strconv.ParseFloatstrconv.ParseIntstrconv.ParseUint,如果基数为 0,则可以在数字之间使用下划线以提高可读性。有关详细信息,请参阅 语言更改

strings

新的 ToValidUTF8 函数返回给定字符串的副本,其中每个无效 UTF-8 字节序列运行都替换为给定字符串。

sync

Mutex.LockMutex.UnlockRWMutex.LockRWMutex.RUnlockOnce.Do 的快速路径现在已内联到其调用者中。对于 amd64 上的无竞争情况,这些更改使 Once.Do 的速度提高了两倍,并且 Mutex/RWMutex 方法的速度提高了 10%。

大型 Pool 不再增加停止世界暂停时间。

Pool 不再需要在每次 GC 后完全重新填充。它现在跨 GC 保留一些对象,而不是释放所有对象,从而减少了 Pool 重度用户的负载峰值。

syscall

已从 Darwin 构建中删除了 _getdirentries64 的使用,以允许将 Go 二进制文件上传到 macOS App Store。

已在 SysProcAttr 中引入了新的 ProcessAttributesThreadAttributes 字段,用于 Windows,在创建新进程时公开安全设置。

在 Windows 上,零 Chmod 模式下不再返回 EINVAL

可以使用 errors.Is 将类型为 Errno 的值与 os 包中的错误值(如 ErrExist)进行测试。

syscall/js

TypedArrayOf 已被 CopyBytesToGoCopyBytesToJS 替换,用于在字节切片和 Uint8Array 之间复制字节。

testing

运行基准测试时,B.N 不再舍入。

新的方法 B.ReportMetric 允许用户报告自定义基准测试指标并覆盖内置指标。

测试标志现在注册在新的 Init 函数中,该函数由测试的生成 main 函数调用。因此,测试标志现在仅在运行测试二进制文件时才注册,并且在包初始化期间调用 flag.Parse 的包可能会导致测试失败。

text/scanner

扫描程序已更新为识别新的 Go 数字文字,特别是带有 0b/0B 前缀的二进制文字、带有 0o/0O 前缀的八进制文字以及带有十六进制尾数的浮点数。此外,新的 AllowDigitSeparators 模式允许数字文字包含下划线作为数字分隔符(默认情况下关闭以确保向后兼容)。有关详细信息,请参阅 语言更改

text/template

新的 切片函数 返回通过以下参数对第一个参数进行切片的结果。

time

FormatParse 现在支持一年中的某一天。

新的 Duration 方法 MicrosecondsMilliseconds 将持续时间作为其各自命名单位的整数计数返回。

unicode

整个系统中的 unicode 包和相关支持已从 Unicode 10.0 升级到 Unicode 11.0,它添加了 684 个新字符,包括 7 个新脚本和 66 个新的表情符号。