Go 1.20 发行说明

Go 1.20 简介

最新的 Go 版本 1.20 在 Go 1.19 发布六个月后到来。其大部分更改都在工具链、运行时和库的实现中。一如既往,此版本保持了 Go 1 兼容性承诺。我们预计几乎所有 Go 程序都将像以前一样继续编译和运行。

语言变化

Go 1.20 包含四项语言更改。

Go 1.17 添加了从切片到数组指针的转换。Go 1.20 将其扩展为允许从切片到数组的转换:给定切片 x,现在可以编写 [4]byte(x) 而不是 *(*[4]byte)(x)

unsafe定义了三个新函数 SliceDataStringStringData。与 Go 1.17 的 Slice 一起,这些函数现在提供了构造和解构切片和字符串值的完整能力,而无需依赖它们的精确表示。

规范现在定义了结构体值逐字段进行比较,按照它们在结构体类型定义中出现的顺序考虑字段,并在第一个不匹配处停止。以前的规范可能被解读为所有字段都需要在第一个不匹配之后进行比较。类似地,规范现在定义了数组值逐元素进行比较,按递增索引顺序。在这两种情况下,差异影响了某些比较是否必须引发恐慌。现有程序不变:新的规范措辞描述了实现一直以来的做法。

可比较类型(例如普通接口)现在可以满足 comparable 约束,即使类型参数不是严格可比较的(比较可能在运行时引发恐慌)。这使得可以使用非严格可比较的类型参数(例如接口类型,或包含接口类型的复合类型)实例化受 comparable 约束的类型参数(例如用于用户定义的泛型映射键的类型参数)。

移植

Windows

Go 1.20 是最后一个可以在 Windows 7、8、Server 2008 和 Server 2012 的任何版本上运行的版本。Go 1.21 将至少需要 Windows 10 或 Server 2016。

Darwin 和 iOS

Go 1.20 是最后一个可以在 macOS 10.13 High Sierra 或 10.14 Mojave 上运行的版本。Go 1.21 将需要 macOS 10.15 Catalina 或更高版本。

FreeBSD/RISC-V

Go 1.20 添加了对 RISC-V 上的 FreeBSD 的实验性支持 (GOOS=freebsd, GOARCH=riscv64)。

工具

Go 命令

目录 $GOROOT/pkg 不再存储标准库的预编译包归档:go install 不再写入它们,go build 不再检查它们,Go 发行版也不再随附它们。相反,标准库中的包会根据需要构建并缓存到构建缓存中,就像 GOROOT 之外的包一样。此更改减少了 Go 发行版的大小,并避免了使用 cgo 的包的 C 工具链偏差。

go test -json 的实现得到了改进,使其更加健壮。运行 go test -json 的程序不需要任何更新。直接调用 go tool test2json 的程序现在应该使用 -v=test2json 运行测试二进制文件(例如,go test -v=test2json./pkg.test -test.v=test2json),而不是普通的 -v

go test -json 的一个相关更改是在每个测试程序执行开始时添加一个 Action 设置为 start 的事件。当使用 go 命令运行多个测试时,这些启动事件保证以与命令行上命名的包相同的顺序发出。

go 命令现在定义了架构特性构建标签,例如 amd64.v2,以允许根据特定架构特性的存在或不存在选择包实现文件。详情请参阅 go help buildconstraint

go 子命令现在接受 -C <dir>,用于在执行命令之前更改目录到 <dir>,这对于需要在多个不同模块中执行命令的脚本可能很有用。

go buildgo test 命令不再接受 -i 标志,该标志已 自 Go 1.16 起弃用

go generate 命令现在接受 -skip <pattern> 来跳过匹配 <pattern>//go:generate 指令。

go test 命令现在接受 -skip <pattern> 来跳过匹配 <pattern> 的测试、子测试或示例。

当主模块位于 GOPATH/src 中时,go install 不再将非 main 包的库安装到 GOPATH/pkg,并且 go list 不再报告此类包的 Target 字段。(在模块模式下,编译的包只存储在构建缓存中,但一个 bug 导致 GOPATH 安装目标意外地仍然有效。)

go buildgo install 和其他与构建相关的命令现在支持 -pgo 标志,该标志启用配置文件引导优化,这在下面的编译器部分中有更详细的描述。-pgo 标志指定配置文件的文件路径。指定 -pgo=auto 会导致 go 命令在主包的目录中搜索名为 default.pgo 的文件,如果存在则使用它。此模式目前要求在命令行上指定单个主包,但我们计划在未来的版本中取消此限制。指定 -pgo=off 会关闭配置文件引导优化。

go buildgo install 和其他与构建相关的命令现在支持 -cover 标志,该标志使用代码覆盖率检测构建指定目标。这在下面的覆盖率部分中有更详细的描述。

go version

go version -m 命令现在支持读取更多类型的 Go 二进制文件,最值得注意的是,使用 go build -buildmode=c-shared 构建的 Windows DLL 和没有执行权限的 Linux 二进制文件。

Cgo

在没有 C 工具链的系统上,go 命令现在默认禁用 cgo。更具体地说,当 CGO_ENABLED 环境变量未设置、CC 环境变量未设置,并且在路径中找不到默认的 C 编译器(通常是 clanggcc)时,CGO_ENABLED 默认值为 0。与往常一样,可以通过显式设置 CGO_ENABLED 来覆盖默认值。

默认更改最重要的影响是,当 Go 安装在没有 C 编译器的系统上时,它现在将使用纯 Go 构建来构建标准库中使用 cgo 的包,而不是使用预分发的包归档(如上文所述已删除)或尝试使用 cgo 并失败。这使得 Go 在某些最小的容器环境以及 macOS 上工作得更好,在 macOS 上,自 Go 1.16 以来,基于 cgo 的包就没有使用过预分发的包归档。

标准库中使用 cgo 的包是 netos/userplugin。在 macOS 上,netos/user 包已被重写为不使用 cgo:现在 cgo 和非 cgo 构建以及交叉编译构建都使用相同的代码。在 Windows 上,netos/user 包从未使用过 cgo。在其他系统上,禁用 cgo 的构建将使用这些包的纯 Go 版本。

一个结果是,在 macOS 上,如果使用 net 包的 Go 代码使用 -buildmode=c-archive 构建,将生成的归档链接到 C 程序需要在链接 C 代码时传递 -lresolv

在 macOS 上,竞争检测器已被重写为不使用 cgo:启用竞争检测器的程序可以在没有 Xcode 的情况下构建和运行。在 Linux 和其他 Unix 系统以及 Windows 上,需要主机 C 工具链才能使用竞争检测器。

覆盖率

Go 1.20 支持收集程序(应用程序和集成测试)的代码覆盖率配置文件,而不仅仅是单元测试。

要收集程序的覆盖率数据,请使用 go build-cover 标志构建它,然后将环境变量 GOCOVERDIR 设置为覆盖率配置文件的输出目录,然后运行生成的二进制文件。有关如何入门的更多信息,请参阅“集成测试覆盖率”着陆页。有关设计和实现的详细信息,请参阅提案

Vet

改进了对嵌套函数捕获循环变量的检测

vet 工具现在报告在子测试函数体内调用 T.Parallel() 后对循环变量的引用。此类引用可能会观察到来自不同迭代的变量值(通常导致测试用例被跳过)或由于未同步的并发访问而导致无效状态。

该工具还在更多地方检测引用错误。以前它只考虑循环体的最后一条语句,但现在它递归地检查 if、switch 和 select 语句中的最后一条语句。

不正确时间格式的新诊断

vet 工具现在报告使用时间格式 2006-02-01 (yyyy-dd-mm) 与 Time.Formattime.Parse。这种格式不出现在常见日期标准中,但在尝试使用 ISO 8601 日期格式 (yyyy-mm-dd) 时经常错误地使用。

运行时

垃圾收集器的一些内部数据结构进行了重新组织,以提高空间和 CPU 效率。此更改减少了内存开销并将整体 CPU 性能提高了高达 2%。

在某些情况下,垃圾收集器在 goroutine 辅助方面的行为不再那么不稳定。

Go 1.20 添加了一个新的 runtime/coverage 包,其中包含用于从通过 os.Exit() 不终止的长时间运行和/或服务器程序在运行时写入覆盖率配置文件数据的 API。

编译器

Go 1.20 添加了对配置文件引导优化 (PGO) 的预览支持。PGO 使工具链能够根据运行时配置文件信息执行应用程序和工作负载特定的优化。目前,编译器支持 pprof CPU 配置文件,这些配置文件可以通过常规方式收集,例如 runtime/pprofnet/http/pprof 包。要启用 PGO,如上文所述,通过 -pgo 标志将 pprof 配置文件文件的路径传递给 go build。Go 1.20 使用 PGO 在热调用站点更积极地内联函数。一组代表性 Go 程序的基准测试表明,启用配置文件引导的内联优化可将性能提高约 3-4%。有关详细文档,请参阅 PGO 用户指南。我们计划在未来版本中添加更多配置文件引导优化。请注意,配置文件引导优化是一个预览功能,因此请谨慎使用。

Go 1.20 编译器将其前端升级为使用一种处理编译器内部数据的新方法,这修复了几个泛型类型问题,并启用了泛型函数和方法中的类型声明。

编译器现在默认通过编译器错误拒绝匿名接口循环。这些是由于嵌入式接口的复杂使用而产生的,并且一直存在微妙的正确性问题,但我们没有证据表明它们在实践中被实际使用。假设没有用户报告受此更改的不利影响,我们计划更新 Go 1.22 的语言规范以正式禁止它们,以便工具作者也可以停止支持它们。

Go 1.18 和 1.19 在构建速度方面出现了退步,这主要是由于添加了对泛型的支持和后续工作。Go 1.20 将构建速度提高了高达 10%,使其恢复到 Go 1.17 的水平。相对于 Go 1.19,生成的代码性能也普遍略有改善。

链接器

在 Linux 上,链接器现在在链接时选择 glibcmusl 的动态解释器。

在 Windows 上,Go 链接器现在支持基于 LLVM 的现代 C 工具链。

Go 1.20 使用 go:type: 前缀表示编译器生成的符号,而不是 go.type.。这避免了名称以 go. 开头的用户包的混淆。debug/gosym 包理解 Go 1.20 及更高版本构建的二进制文件的这种新命名约定。

引导

从源代码构建 Go 版本且未设置 GOROOT_BOOTSTRAP 时,Go 的早期版本会在目录 $HOME/go1.4(Windows 上为 %HOMEDRIVE%%HOMEPATH%\go1.4)中查找 Go 1.4 或更高版本的引导工具链。Go 1.18 和 Go 1.19 首先查找 $HOME/go1.17$HOME/sdk/go1.17,然后再回退到 $HOME/go1.4,以期望在引导 Go 1.20 时需要 Go 1.17。Go 1.20 确实需要 Go 1.17 版本进行引导,但我们意识到我们应该采用引导工具链的最新点发布版本,因此它需要 Go 1.17.13。Go 1.20 会查找 $HOME/go1.17.13$HOME/sdk/go1.17.13,然后再回退到 $HOME/go1.4(以支持那些硬编码路径 $HOME/go1.4 但已在那里安装了更新的 Go 工具链的系统)。将来,我们计划大约每年将引导工具链向前推进一次,特别是我们预计 Go 1.22 将需要 Go 1.20 的最终点发布版本进行引导。

标准库

新的 crypto/ecdh 包

Go 1.20 添加了一个新的 crypto/ecdh 包,以提供对 NIST 曲线和 Curve25519 上的椭圆曲线 Diffie-Hellman 密钥交换的显式支持。

程序应使用 crypto/ecdh 代替 crypto/elliptic 中较低级别的 ECDH 功能,对于更高级的用例则使用第三方模块。

包装多个错误

Go 1.20 扩展了对错误包装的支持,允许一个错误包装多个其他错误。

错误 e 可以通过提供返回 []errorUnwrap 方法来包装多个错误。

errors.Iserrors.As 函数已更新以检查多重包装的错误。

fmt.Errorf 函数现在支持 %w 格式动词的多次出现,这将导致它返回一个包装所有这些错误操作数的错误。

新函数 errors.Join 返回一个包装错误列表的错误。

HTTP ResponseController

新的 "net/http".ResponseController 类型提供对 "net/http".ResponseWriter 接口未处理的扩展的每请求功能的访问。

以前,我们通过定义 ResponseWriter 可以实现的可选接口(例如 Flusher)来添加新的每请求功能。这些接口不可发现且使用笨拙。

ResponseController 类型提供了一种更清晰、更易于发现的方式来添加每处理程序控件。Go 1.20 中也添加了两个此类控件:SetReadDeadlineSetWriteDeadline,它们允许设置每请求的读取和写入截止时间。例如:

func RequestHandler(w ResponseWriter, r *Request) {
  rc := http.NewResponseController(w)
  rc.SetWriteDeadline(time.Time{}) // disable Server.WriteTimeout when sending a large response
  io.Copy(w, bigData)
}

新的 ReverseProxy Rewrite 钩子

httputil.ReverseProxy 转发代理包含一个新的 Rewrite 钩子函数,取代了之前的 Director 钩子。

Rewrite 钩子接受一个 ProxyRequest 参数,其中包括代理收到的入站请求和它将发送的出站请求。与只对出站请求操作的 Director 钩子不同,这允许 Rewrite 钩子避免某些恶意入站请求可能导致钩子添加的标头在转发之前被删除的情况。请参阅 问题 #50580

ProxyRequest.SetURL 方法将出站请求路由到提供的目标,并取代了 NewSingleHostReverseProxy 函数。与 NewSingleHostReverseProxy 不同,SetURL 还设置出站请求的 Host 标头。

ProxyRequest.SetXForwarded 方法设置出站请求的 X-Forwarded-ForX-Forwarded-HostX-Forwarded-Proto 标头。当使用 Rewrite 时,这些标头默认不会添加。

使用这些功能的 Rewrite 钩子示例如下:

proxyHandler := &httputil.ReverseProxy{
  Rewrite: func(r *httputil.ProxyRequest) {
    r.SetURL(outboundURL) // Forward request to outboundURL.
    r.SetXForwarded()     // Set X-Forwarded-* headers.
    r.Out.Header.Set("X-Additional-Header", "header set by the proxy")
  },
}

当传入请求没有 User-Agent 标头时,ReverseProxy 不再向转发请求添加 User-Agent 标头。

对库的微小更改

一如既往,库中进行了各种小的更改和更新,始终牢记 Go 1 的兼容性承诺。还有各种未在此处列出的性能改进。

archive/tar

当设置 GODEBUG=tarinsecurepath=0 环境变量时,Reader.Next 方法现在将为文件名是绝对路径、引用当前目录之外的位置、包含无效字符或(在 Windows 上)是保留名称(如 NUL)的条目返回错误 ErrInsecurePath。Go 的未来版本可能会默认禁用不安全路径。

archive/zip

当设置 GODEBUG=zipinsecurepath=0 环境变量时,NewReader 现在将在打开包含文件名是绝对路径、引用当前目录之外的位置、包含无效字符或(在 Windows 上)是保留名称(如 NUL)的任何文件的归档时返回错误 ErrInsecurePath。Go 的未来版本可能会默认禁用不安全路径。

从包含文件数据的目录文件读取现在将返回错误。zip 规范不允许目录文件包含文件数据,因此此更改仅影响从无效归档读取。

bytes

新的 CutPrefixCutSuffix 函数类似于 TrimPrefixTrimSuffix,但也会报告字符串是否被修剪。

新的 Clone 函数分配一个字节切片的副本。

context

新的 WithCancelCause 函数提供了一种使用给定错误取消上下文的方法。可以通过调用新的 Cause 函数检索该错误。

crypto/ecdsa

在使用支持的曲线时,所有操作现在都在恒定时间内实现。这导致 CPU 时间增加了 5% 到 30%,主要影响 P-384 和 P-521。

新的 PrivateKey.ECDH 方法将 ecdsa.PrivateKey 转换为 ecdh.PrivateKey

crypto/ed25519

PrivateKey.Sign 方法和 VerifyWithOptions 函数现在支持使用 Ed25519ph 签名预哈希消息,由返回 crypto.SHA512Options.HashFunc 指示。它们现在还支持带上下文的 Ed25519ctx 和 Ed25519ph,由设置新的 Options.Context 字段指示。

crypto/rsa

新字段 OAEPOptions.MGFHash 允许为 OAEP 解密单独配置 MGF1 哈希。

crypto/rsa 现在使用新的、更安全的、恒定时间后端。这导致解密操作的 CPU 运行时增加了大约 15%(amd64 上的 RSA-2048)到 45%(arm64 上的 RSA-4096),在 32 位架构上更多。加密操作比以前慢大约 20 倍(但仍然比解密快 5-10 倍)。预计性能将在未来版本中得到改善。程序不得修改或手动生成 PrecomputedValues 的字段。

crypto/subtle

新函数 XORBytes 将两个字节切片进行异或操作。

crypto/tls

解析后的证书现在在所有主动使用该证书的客户端之间共享。在对服务器或共享其证书链任何部分的服务器集合进行许多并发连接的程序中,内存节省可能非常显著。

对于由于证书验证失败导致的握手失败,TLS 客户端和服务器现在返回新类型 CertificateVerificationError 的错误,其中包括提供的证书。

crypto/x509

ParsePKCS8PrivateKeyMarshalPKCS8PrivateKey 现在支持 *crypto/ecdh.PrivateKey 类型的密钥。ParsePKIXPublicKeyMarshalPKIXPublicKey 现在支持 *crypto/ecdh.PublicKey 类型的密钥。解析 NIST 曲线密钥仍然返回 *ecdsa.PublicKey*ecdsa.PrivateKey 类型的值。使用它们新的 ECDH 方法将其转换为 crypto/ecdh 类型。

新函数 SetFallbackRoots 允许程序定义一组备用根证书,以防在运行时操作系统验证程序或标准平台根包不可用。它最常与新包 golang.org/x/crypto/x509roots/fallback 一起使用,该包将提供最新的根包。

debug/elf

尝试使用 Section.DataSection.Open 返回的读取器从 SHT_NOBITS 部分读取现在会返回错误。

为 LoongArch 系统定义了额外的 R_LARCH_* 常量。

为 PPC64 ELFv2 重定位定义了额外的 R_PPC64_* 常量。

R_PPC64_SECTOFF_LO_DS 的常量值已更正,从 61 到 62。

debug/gosym

由于 Go 的符号命名约定发生了变化,处理 Go 二进制文件的工具应使用 Go 1.20 的 debug/gosym 包来透明地处理旧和新的二进制文件。

debug/pe

为 RISC-V 系统定义了额外的 IMAGE_FILE_MACHINE_RISCV* 常量。

encoding/binary

ReadVarintReadUvarint 函数现在在读取部分值后将返回 io.ErrUnexpectedEOF,而不是 io.EOF

encoding/xml

新的 Encoder.Close 方法可以在编码完成后检查未关闭的元素。

解码器现在拒绝带有多个冒号的元素和属性名称,例如 <a:b:c>,以及解析为空字符串的命名空间,例如 xmlns:a=""

解码器现在拒绝在开始标签和结束标签中使用不同命名空间前缀的元素,即使这些前缀都表示相同的命名空间。

errors

新的 Join 函数返回一个包装错误列表的错误。

fmt

Errorf 函数支持 %w 格式动词的多次出现,返回一个解包为所有 %w 参数列表的错误。

新的 FormatString 函数恢复与 State 对应的格式化指令,这在 Formatter 实现中可能很有用。

go/ast

新的 RangeStmt.Range 字段记录 range 语句中 range 关键字的位置。

新的 File.FileStartFile.FileEnd 字段记录整个源文件的开始和结束位置。

go/token

新的 FileSet.RemoveFile 方法从 FileSet 中删除文件。长时间运行的程序可以使用此方法释放与其不再需要的文件相关的内存。

go/types

新的 Satisfies 函数报告类型是否满足约束。此更改与新的语言语义一致,该语义区分满足约束和实现接口。

html/template

Go 1.20.3 及更高版本不允许 ECMAScript 6 模板字面量中的操作。此行为可以通过 GODEBUG=jstmpllitinterp=1 设置恢复。

io

新的 OffsetWriter 包装了一个底层 WriterAt,并提供了 SeekWriteWriteAt 方法,这些方法通过固定量调整其有效的写入偏移位置。

io/fs

新错误 SkipAll 立即但成功地终止 WalkDir

math/big

math/big 包的广泛范围和输入相关的计时使其不适合实现加密。标准库中的加密包不再在攻击者控制的输入上调用非平凡的 Int 方法。将来,判断 math/big 中的错误是否被视为安全漏洞将取决于其对标准库的更广泛影响。

math/rand

math/rand 包现在会自动使用随机值播种全局随机数生成器(由 Float64Int 等顶级函数使用),并且顶级 Seed 函数已被弃用。需要可重现的随机数序列的程序应优先使用 rand.New(rand.NewSource(seed)) 分配自己的随机源。

需要早期一致全局播种行为的程序可以在其环境中设置 GODEBUG=randautoseed=0

顶级 Read 函数已被弃用。在几乎所有情况下,crypto/rand.Read 更合适。

mime

ParseMediaType 函数现在允许重复的参数名称,只要名称的值相同。

mime/multipart

Reader 类型的方法现在包装了底层 io.Reader 返回的错误。

在 Go 1.19.8 及更高版本中,此包限制了它处理的 MIME 数据的大小,以防止恶意输入。Reader.NextPartReader.NextRawPart 将一个部分的标头数量限制为 10000,Reader.ReadForm 将所有 FileHeaders 中标头的总数限制为 10000。这些限制可以通过 GODEBUG=multipartmaxheaders 设置进行调整。Reader.ReadForm 进一步将表单中的部分数量限制为 1000。此限制可以通过 GODEBUG=multipartmaxparts 设置进行调整。

net

LookupCNAME 函数现在在存在 CNAME 记录时始终返回 CNAME 记录的内容。以前在 Unix 系统上以及使用纯 Go 解析器时,如果 CNAME 记录引用一个没有 AAAAACNAME 记录的名称,LookupCNAME 将返回错误。此更改修改了 LookupCNAME 以匹配 Windows 上的先前行为,允许 LookupCNAMECNAME 存在时成功。

Interface.Flags 现在包含新标志 FlagRunning,表示操作活动的接口。一个已管理配置但未活动的接口(例如,因为网线未连接)将设置 FlagUp 但不设置 FlagRunning

新的 Dialer.ControlContext 字段包含一个回调函数,类似于现有的 Dialer.Control 钩子,它额外接受拨号上下文作为参数。当 ControlContext 不为 nil 时,Control 将被忽略。

Go DNS 解析器识别 trust-ad 解析器选项。当 resolv.conf 中设置 options trust-ad 时,Go 解析器将在 DNS 查询中设置 AD 位。解析器不使用响应中的 AD 位。

DNS 解析将检测 /etc/nsswitch.conf 的更改并在文件更改时重新加载。检查最多每五秒进行一次,与以前处理 /etc/hosts/etc/resolv.conf 的方式相同。

net/http

ResponseWriter.WriteHeader 函数现在支持发送 1xx 状态码。

新的 Server.DisableGeneralOptionsHandler 配置设置允许禁用默认的 OPTIONS * 处理程序。

新的 Transport.OnProxyConnectResponse 钩子在 Transport 从代理收到 CONNECT 请求的 HTTP 响应时调用。

HTTP 服务器现在接受包含正文的 HEAD 请求,而不是将其拒绝为无效请求。

net/http 函数返回的 HTTP/2 流错误可以使用 errors.As 转换为 golang.org/x/net/http2.StreamError

cookie 名称的前导和尾随空格将被修剪,而不是被拒绝为无效。例如,现在接受“name =value”的 cookie 设置为设置 cookie“name”。

Expires 字段为空的 Cookie 现在被认为是有效的。Cookie.Valid 仅在设置 Expires 时检查。

net/netip

新的 IPv6LinkLocalAllRoutersIPv6Loopback 函数是 net.IPv6loopbacknet.IPv6linklocalallroutersnet/netip 中的等价物。

os

在 Windows 上,名称 NULMkdirStat 中不再被视为特殊情况。

在 Windows 上,File.Stat 现在在文件是目录时使用文件句柄检索属性。以前它会使用传递给 Open 的路径,如果文件已被移动或替换,该路径可能不再表示文件句柄表示的文件。此更改修改了 Open 以在不使用 FILE_SHARE_DELETE 访问权限的情况下打开目录,这与常规文件的行为匹配。

在 Windows 上,File.Seek 现在支持查找目录的开头。

os/exec

新的 Cmd 字段 CancelWaitDelay 指定当其关联的 Context 被取消或其进程在子进程仍持有 I/O 管道打开时退出时 Cmd 的行为。

path/filepath

新的错误 SkipAll 立即但成功地终止 Walk

新的 IsLocal 函数报告路径是否在词法上相对于目录。例如,如果 IsLocal(p)true,则 Open(p) 将引用一个词法上位于当前目录下的文件。

reflect

新的 Value.ComparableValue.Equal 方法可用于比较两个 Value 的相等性。Comparable 报告对于给定 Value 接收器,Equal 是否是有效操作。

新的 Value.Grow 方法扩展切片以保证另一个 n 个元素的空间。

新的 Value.SetZero 方法将值设置为其类型的零值。

Go 1.18 引入了 Value.SetIterKeyValue.SetIterValue 方法。这些是优化:v.SetIterKey(it) 旨在等效于 v.Set(it.Key())。实现错误地省略了对未导出字段使用的检查,而未优化形式中存在该检查。Go 1.20 纠正了这些方法以包含未导出字段检查。

regexp

Go 1.19.2 和 Go 1.18.7 包含一个针对正则表达式解析器的安全修复,使其拒绝会消耗过多内存的超大表达式。由于 Go 补丁版本不引入新的 API,解析器在这种情况下返回 syntax.ErrInternalError。Go 1.20 添加了一个更具体的错误 syntax.ErrLarge,解析器现在返回该错误。

runtime/cgo

Go 1.20 添加了新的 Incomplete 标记类型。cgo 生成的代码将使用 cgo.Incomplete 来标记不完整的 C 类型。

runtime/metrics

Go 1.20 添加了新的支持指标,包括当前的 GOMAXPROCS 设置 (/sched/gomaxprocs:threads)、执行的 cgo 调用次数 (/cgo/go-to-c-calls:calls)、总互斥锁阻塞时间 (/sync/mutex/wait/total:seconds) 以及垃圾回收中花费的各种时间度量。

基于时间的直方图指标现在精度较低,但占用内存少得多。

runtime/pprof

互斥锁配置文件样本现在已预先缩放,修复了如果采样率在执行期间发生变化,旧互斥锁配置文件样本将被错误缩放的问题。

在 Windows 上收集的配置文件现在包含内存映射信息,修复了位置无关二进制文件的符号化问题。

runtime/trace

垃圾收集器的后台清扫器现在让步的频率更低,从而在执行跟踪中产生更少的多余事件。

strings

新的 CutPrefixCutSuffix 函数类似于 TrimPrefixTrimSuffix,但也会报告字符串是否被修剪。

sync

新的 Map 方法 SwapCompareAndSwapCompareAndDelete 允许原子更新现有映射条目。

syscall

在 FreeBSD 上,已删除 FreeBSD 11 及更早版本所需的兼容性填充。

在 Linux 上,为 SysProcAttr.Cloneflags 字段定义了额外的 CLONE_* 常量。

在 Linux 上,新的 SysProcAttr.CgroupFDSysProcAttr.UseCgroupFD 字段提供了一种将子进程放入特定 cgroup 的方法。

testing

新方法 B.Elapsed 报告基准测试的当前经过时间,这对于计算与 ReportMetric 一起报告的速率可能很有用。

从传递给 T.Cleanup 的函数中调用 T.Run 从未明确定义,现在将导致恐慌。

time

新的时间布局常量 DateTimeDateOnlyTimeOnly 为公共 Go 源代码调查中使用的三种最常见布局字符串提供了名称。

新的 Time.Compare 方法比较两个时间。

Parse 现在忽略输入中的亚纳秒精度,而不是将这些数字报告为错误。

Time.MarshalJSON 方法现在对 RFC 3339 的遵守更加严格。

unicode/utf16

新的 AppendRune 函数将给定符文的 UTF-16 编码附加到 uint16 切片,类似于 utf8.AppendRune