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
一样,这些函数现在提供了构建和解构切片和字符串值的完整能力,而无需依赖于它们的精确表示。
规范现在定义了结构体值的比较是按字段依次进行的,考虑结构体类型定义中字段的出现顺序,并在第一个不匹配时停止。之前规范可以理解为在第一个不匹配后需要比较所有字段。同样,规范现在定义了数组值的比较是按元素依次进行的,按索引递增顺序。在这两种情况下,差异都会影响某些比较是否必须引发 panic。现有的程序没有改变:新的规范措辞描述了实现一直以来的行为。
可比较类型(如普通接口)现在可以满足 comparable
约束,即使类型参数不是严格可比较的(比较可能在运行时引发 panic)。这使得可以将受 comparable
约束的类型参数(例如,用户定义的泛型 map 键的类型参数)实例化为非严格可比较的类型参数,例如接口类型或包含接口类型的复合类型。
移植
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 添加了对 FreeBSD 在 RISC-V 上的实验性支持 (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
字段。(在模块模式下,编译后的包仅存储在 构建缓存 中,但 一个错误 导致 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
go
命令现在在没有 C 工具链的系统上默认禁用 cgo
。更具体地说,当 CGO_ENABLED
环境变量未设置时,CC
环境变量未设置,并且默认的 C 编译器(通常是 clang
或 gcc
)在路径中找不到时,CGO_ENABLED
默认设置为 0
。与往常一样,您可以通过显式设置 CGO_ENABLED
来覆盖默认值。
默认更改的最重要影响是,当 Go 安装在没有 C 编译器的系统上时,它现在将使用纯 Go 构建用于标准库中使用 cgo 的包,而不是使用预分发的包归档文件(已删除,如 上面所述)或尝试使用 cgo 并失败。这使得 Go 在某些最小容器环境以及 macOS 上运行得更好,自 Go 1.16 以来,macOS 上不再使用预分发的包归档文件用于基于 cgo 的包。
标准库中使用 cgo 的包是 net
、os/user
和 plugin
。在 macOS 上,net
和 os/user
包已经重写为不使用 cgo:相同的代码现在用于 cgo 和非 cgo 构建以及交叉编译构建。在 Windows 上,net
和 os/user
包从未使用过 cgo。在其他系统上,禁用 cgo 的构建将使用这些包的纯 Go 版本。
一个结果是,在 macOS 上,如果使用 -buildmode=c-archive
构建使用 net
包的 Go 代码,则将生成的归档文件链接到 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
工具现在会报告使用 Time.Format
和 time.Parse
时使用时间格式 2006-02-01 (yyyy-dd-mm)。此格式未出现在常见日期标准中,但在尝试使用 ISO 8601 日期格式 (yyyy-mm-dd) 时经常被误用。
运行时
垃圾收集器的一些内部数据结构经过重新组织,使其在空间和 CPU 效率方面都更高。此更改减少了内存开销,并使整体 CPU 性能提高了高达 2%。
在某些情况下,垃圾收集器在协程辅助方面的行为不那么不稳定。
Go 1.20 添加了一个新的 runtime/coverage
包,其中包含 API,用于从长时间运行和/或不通过 os.Exit()
终止的服务器程序在运行时写入覆盖率配置文件数据。
编译器
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.4
之前,首先会查找 $HOME/go1.17
或 $HOME/sdk/go1.17
,以期在引导 Go 1.20 时需要使用 Go 1.17。Go 1.20 确实需要 Go 1.17 版本才能进行引导,但我们意识到应该采用引导工具链的最新版本,因此它需要 Go 1.17.13。Go 1.20 在回退到 $HOME/go1.4
之前会查找 $HOME/go1.17.13
或 $HOME/sdk/go1.17.13
(以支持将路径 $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 重写钩子
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")
},
}
ReverseProxy
不再在传入请求没有 User-Agent
标头时为转发请求添加 User-Agent
标头。
对库的次要更改
与往常一样,对库进行了各种次要更改和更新,并牢记 Go 1 的 兼容性承诺。这里没有列出各种性能改进。
archive/tar
当设置了 GODEBUG=tarinsecurepath=0
环境变量时, Reader.Next
方法现在会为具有以下文件名(绝对路径、引用当前目录之外的位置、包含无效字符或(在 Windows 上)为保留名称,如 NUL
)的条目返回错误 ErrInsecurePath
。Go 的未来版本可能会默认禁用不安全的路径。
archive/zip
当设置了 GODEBUG=zipinsecurepath=0
环境变量时, NewReader
现在会在打开包含任何具有以下文件名的归档文件时返回错误 ErrInsecurePath
:绝对路径、引用当前目录之外的位置、包含无效字符或(在 Windows 上)为保留名称,如 NUL
。Go 的未来版本可能会默认禁用不安全的路径。
从包含文件数据的目录文件读取现在将返回错误。zip 规范不允许目录文件包含文件数据,因此此更改仅影响从无效归档文件读取。
字节
新的 CutPrefix
和 CutSuffix
函数类似于 TrimPrefix
和 TrimSuffix
,但也会报告字符串是否已修剪。
新的 Clone
函数分配字节切片的副本。
上下文
新的 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%(RSA-2048 在 amd64 上)到 45%(RSA-4096 在 arm64 上),并且在 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
关键字的位置。
新的 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
新的错误 SkipAll
会立即但成功地终止 WalkDir
。
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 数据大小限制为 10000,以防止恶意输入。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 设置为设置“name” Cookie。
具有空 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
指定了 Cmd
在其关联的 Context
被取消或其进程退出时(子进程仍持有 I/O 管道)的行为。
path/filepath
新的 IsLocal
函数报告路径是否在词汇上是目录的本地路径。例如,如果 IsLocal(p)
为 true
,则 Open(p)
将引用在当前目录根目录下词汇上位于子树中的文件。
reflect
新的 Value.Comparable
和 Value.Equal
方法可用于比较两个 Value
的相等性。Comparable
报告 Equal
是否是给定 Value
接收器的有效操作。
新的 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
垃圾收集器的后台清除程序现在减少了 yield 频率,导致执行跟踪中出现明显较少的额外事件。
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
从未明确定义,现在将导致 panic。
time
新的时间布局常量 DateTime
、DateOnly
和 TimeOnly
为在对公共 Go 源代码的调查中使用的三个最常见布局字符串提供了名称。
新的 Time.Compare
方法比较两个时间。
Parse
现在会忽略输入中的亚纳秒精度,而不是将这些数字报告为错误。
Time.MarshalJSON
方法现在对遵守 RFC 3339 更严格。
unicode/utf16
新的 AppendRune
函数将给定字符的 UTF-16 编码追加到 uint16 切片,类似于 utf8.AppendRune
.