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
包定义了三个新函数 SliceData
、String
和 StringData
。与 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
build
和 go
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
build
、go
install
和其他与构建相关的命令现在支持 -pgo
标志,该标志启用配置文件引导优化,这在下面的编译器部分中有更详细的描述。-pgo
标志指定配置文件的文件路径。指定 -pgo=auto
会导致 go
命令在主包的目录中搜索名为 default.pgo
的文件,如果存在则使用它。此模式目前要求在命令行上指定单个主包,但我们计划在未来的版本中取消此限制。指定 -pgo=off
会关闭配置文件引导优化。
go
build
、go
install
和其他与构建相关的命令现在支持 -cover
标志,该标志使用代码覆盖率检测构建指定目标。这在下面的覆盖率部分中有更详细的描述。
go
version
go
version
-m
命令现在支持读取更多类型的 Go 二进制文件,最值得注意的是,使用 go
build
-buildmode=c-shared
构建的 Windows DLL 和没有执行权限的 Linux 二进制文件。
Cgo
在没有 C 工具链的系统上,go
命令现在默认禁用 cgo
。更具体地说,当 CGO_ENABLED
环境变量未设置、CC
环境变量未设置,并且在路径中找不到默认的 C 编译器(通常是 clang
或 gcc
)时,CGO_ENABLED
默认值为 0
。与往常一样,可以通过显式设置 CGO_ENABLED
来覆盖默认值。
默认更改最重要的影响是,当 Go 安装在没有 C 编译器的系统上时,它现在将使用纯 Go 构建来构建标准库中使用 cgo 的包,而不是使用预分发的包归档(如上文所述已删除)或尝试使用 cgo 并失败。这使得 Go 在某些最小的容器环境以及 macOS 上工作得更好,在 macOS 上,自 Go 1.16 以来,基于 cgo 的包就没有使用过预分发的包归档。
标准库中使用 cgo 的包是 net
、os/user
和 plugin
。在 macOS 上,net
和 os/user
包已被重写为不使用 cgo:现在 cgo 和非 cgo 构建以及交叉编译构建都使用相同的代码。在 Windows 上,net
和 os/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.Format
和 time.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/pprof
或 net/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 上,链接器现在在链接时选择 glibc
或 musl
的动态解释器。
在 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
可以通过提供返回 []error
的 Unwrap
方法来包装多个错误。
errors.Is
和 errors.As
函数已更新以检查多重包装的错误。
fmt.Errorf
函数现在支持 %w
格式动词的多次出现,这将导致它返回一个包装所有这些错误操作数的错误。
新函数 errors.Join
返回一个包装错误列表的错误。
HTTP ResponseController
新的 "net/http".ResponseController
类型提供对 "net/http".ResponseWriter
接口未处理的扩展的每请求功能的访问。
以前,我们通过定义 ResponseWriter
可以实现的可选接口(例如 Flusher
)来添加新的每请求功能。这些接口不可发现且使用笨拙。
ResponseController
类型提供了一种更清晰、更易于发现的方式来添加每处理程序控件。Go 1.20 中也添加了两个此类控件:SetReadDeadline
和 SetWriteDeadline
,它们允许设置每请求的读取和写入截止时间。例如:
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-For
、X-Forwarded-Host
和 X-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
新的 CutPrefix
和 CutSuffix
函数类似于 TrimPrefix
和 TrimSuffix
,但也会报告字符串是否被修剪。
新的 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.SHA512
的 Options.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
ParsePKCS8PrivateKey
和 MarshalPKCS8PrivateKey
现在支持 *crypto/ecdh.PrivateKey
类型的密钥。ParsePKIXPublicKey
和 MarshalPKIXPublicKey
现在支持 *crypto/ecdh.PublicKey
类型的密钥。解析 NIST 曲线密钥仍然返回 *ecdsa.PublicKey
和 *ecdsa.PrivateKey
类型的值。使用它们新的 ECDH
方法将其转换为 crypto/ecdh
类型。
新函数 SetFallbackRoots
允许程序定义一组备用根证书,以防在运行时操作系统验证程序或标准平台根包不可用。它最常与新包 golang.org/x/crypto/x509roots/fallback 一起使用,该包将提供最新的根包。
debug/elf
尝试使用 Section.Data
或 Section.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
ReadVarint
和 ReadUvarint
函数现在在读取部分值后将返回 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.FileStart
和 File.FileEnd
字段记录整个源文件的开始和结束位置。
go/token
新的 FileSet.RemoveFile
方法从 FileSet
中删除文件。长时间运行的程序可以使用此方法释放与其不再需要的文件相关的内存。
go/types
新的 Satisfies
函数报告类型是否满足约束。此更改与新的语言语义一致,该语义区分满足约束和实现接口。
html/template
Go 1.20.3 及更高版本不允许 ECMAScript 6 模板字面量中的操作。此行为可以通过 GODEBUG=jstmpllitinterp=1
设置恢复。
io
新的 OffsetWriter
包装了一个底层 WriterAt
,并提供了 Seek
、Write
和 WriteAt
方法,这些方法通过固定量调整其有效的写入偏移位置。
io/fs
math/big
math/big 包的广泛范围和输入相关的计时使其不适合实现加密。标准库中的加密包不再在攻击者控制的输入上调用非平凡的 Int 方法。将来,判断 math/big 中的错误是否被视为安全漏洞将取决于其对标准库的更广泛影响。
math/rand
math/rand 包现在会自动使用随机值播种全局随机数生成器(由 Float64
和 Int
等顶级函数使用),并且顶级 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.NextPart
和 Reader.NextRawPart
将一个部分的标头数量限制为 10000,Reader.ReadForm
将所有 FileHeaders
中标头的总数限制为 10000。这些限制可以通过 GODEBUG=multipartmaxheaders
设置进行调整。Reader.ReadForm
进一步将表单中的部分数量限制为 1000。此限制可以通过 GODEBUG=multipartmaxparts
设置进行调整。
net
LookupCNAME
函数现在在存在 CNAME
记录时始终返回 CNAME
记录的内容。以前在 Unix 系统上以及使用纯 Go 解析器时,如果 CNAME
记录引用一个没有 A
、AAAA
或 CNAME
记录的名称,LookupCNAME
将返回错误。此更改修改了 LookupCNAME
以匹配 Windows 上的先前行为,允许 LookupCNAME
在 CNAME
存在时成功。
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
新的 IPv6LinkLocalAllRouters
和 IPv6Loopback
函数是 net.IPv6loopback
和 net.IPv6linklocalallrouters
在 net/netip
中的等价物。
os
在 Windows 上,名称 NUL
在 Mkdir
和 Stat
中不再被视为特殊情况。
在 Windows 上,File.Stat
现在在文件是目录时使用文件句柄检索属性。以前它会使用传递给 Open
的路径,如果文件已被移动或替换,该路径可能不再表示文件句柄表示的文件。此更改修改了 Open
以在不使用 FILE_SHARE_DELETE
访问权限的情况下打开目录,这与常规文件的行为匹配。
在 Windows 上,File.Seek
现在支持查找目录的开头。
os/exec
新的 Cmd
字段 Cancel
和 WaitDelay
指定当其关联的 Context
被取消或其进程在子进程仍持有 I/O 管道打开时退出时 Cmd
的行为。
path/filepath
新的 IsLocal
函数报告路径是否在词法上相对于目录。例如,如果 IsLocal(p)
为 true
,则 Open(p)
将引用一个词法上位于当前目录下的文件。
reflect
新的 Value.Comparable
和 Value.Equal
方法可用于比较两个 Value
的相等性。Comparable
报告对于给定 Value
接收器,Equal
是否是有效操作。
新的 Value.Grow
方法扩展切片以保证另一个 n
个元素的空间。
新的 Value.SetZero
方法将值设置为其类型的零值。
Go 1.18 引入了 Value.SetIterKey
和 Value.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
新的 CutPrefix
和 CutSuffix
函数类似于 TrimPrefix
和 TrimSuffix
,但也会报告字符串是否被修剪。
sync
新的 Map
方法 Swap
、CompareAndSwap
和 CompareAndDelete
允许原子更新现有映射条目。
syscall
在 FreeBSD 上,已删除 FreeBSD 11 及更早版本所需的兼容性填充。
在 Linux 上,为 SysProcAttr.Cloneflags
字段定义了额外的 CLONE_*
常量。
在 Linux 上,新的 SysProcAttr.CgroupFD
和 SysProcAttr.UseCgroupFD
字段提供了一种将子进程放入特定 cgroup 的方法。
testing
新方法 B.Elapsed
报告基准测试的当前经过时间,这对于计算与 ReportMetric
一起报告的速率可能很有用。
从传递给 T.Cleanup
的函数中调用 T.Run
从未明确定义,现在将导致恐慌。
time
新的时间布局常量 DateTime
、DateOnly
和 TimeOnly
为公共 Go 源代码调查中使用的三种最常见布局字符串提供了名称。
新的 Time.Compare
方法比较两个时间。
Parse
现在忽略输入中的亚纳秒精度,而不是将这些数字报告为错误。
Time.MarshalJSON
方法现在对 RFC 3339 的遵守更加严格。
unicode/utf16
新的 AppendRune
函数将给定符文的 UTF-16 编码附加到 uint16 切片,类似于 utf8.AppendRune
。