Go 1.21 发行说明
Go 1.21 简介
最新的 Go 版本 1.21 在 Go 1.20 发布六个月后到来。它的大部分更改都在工具链、运行时和库的实现中。一如既往,此版本保持了 Go 1 的兼容性承诺;事实上,Go 1.21 改进了这一承诺。我们预计几乎所有 Go 程序都将像以前一样继续编译和运行。
Go 1.21 对版本编号做了一个小改动。过去,我们使用 Go 1.N 来指代整个 Go 语言版本和版本家族,以及该家族的第一个版本。从 Go 1.21 开始,第一个版本现在是 Go 1.N.0。今天我们发布的是 Go 1.21 语言及其初始实现 Go 1.21.0 版本。这些说明中提到“Go 1.21”;像 go
version
这样的工具将报告“go1.21.0
”(直到您升级到 Go 1.21.1)。有关新版本编号的详细信息,请参阅“Go 工具链”文档中的“Go 版本”。
语言变化
Go 1.21 向语言中添加了三个新的内置函数。
-
新函数
min
和max
计算给定固定数量参数的最小值(或最大值,对于max
)。有关详细信息,请参阅语言规范。 -
新函数
clear
从映射中删除所有元素或将切片的所有元素归零。有关详细信息,请参阅语言规范。
包初始化顺序现在规定得更精确。新算法是
- 按导入路径对所有包进行排序。
- 重复直到包列表为空
- 找到列表中所有导入都已初始化的第一个包。
- 初始化该包并将其从列表中删除。
这可能会改变某些程序行为,如果它们依赖于未通过显式导入表达的特定初始化顺序。过去版本中,此类程序的行为并未由规范明确定义。新规则提供了明确的定义。
类型推断方面进行了多项改进,以提高其功能和精确度。
- (可能是部分实例化的泛型)函数现在可以以自身也是(可能是部分实例化的)泛型函数的参数调用。编译器将尝试推断被调用者的缺失类型参数(如前所述),对于作为尚未完全实例化的泛型函数的每个参数,也会推断其缺失的类型参数(新增)。典型的用例是对容器(如 slices.IndexFunc)上的泛型函数进行调用,其中函数参数也可能是泛型,并且被调用函数及其参数的类型参数是从容器类型推断出来的。更一般地,如果类型参数可以从赋值中推断出来,泛型函数现在可以在没有显式实例化的情况下使用,当它被赋值给变量或作为结果值返回时。
- 当一个值被赋值给接口时,类型推断现在也会考虑方法:方法签名中使用的类型参数的类型参数可以从匹配方法的相应参数类型中推断出来。
- 类似地,由于类型参数必须实现其相应约束的所有方法,因此会匹配类型参数和约束的方法,这可能导致推断出额外的类型参数。
- 如果不同类型的多个无类型常量参数(例如无类型 int 和无类型浮点常量)传递给具有相同(未另行指定)类型参数类型的参数,现在类型推断会使用与具有无类型常量操作数的运算符相同的方法来确定类型,而不是报告错误。此更改使从无类型常量参数推断的类型与常量表达式的类型保持一致。
- 类型推断在赋值中匹配相应类型时现在是精确的:组件类型(例如切片的元素,或函数签名中的参数类型)必须相同(给定合适的类型参数)才能匹配,否则推断失败。此更改会产生更准确的错误消息:过去类型推断可能错误地成功并导致无效赋值,而现在如果两种类型不可能匹配,编译器会报告推断错误。
更一般地,语言规范中关于类型推断的描述已得到澄清。总之,所有这些更改使类型推断更强大,推断失败更不意外。
Go 1.21 包含我们正在考虑在未来 Go 版本中进行的语言更改的预览:使 for 循环变量为每次迭代一次,而不是每次循环一次,以避免意外的共享错误。有关如何尝试该语言更改的详细信息,请参阅 LoopvarExperiment wiki 页面。
Go 1.21 现在定义:如果一个 goroutine 正在 panic 并且 recover 被 deferred 函数直接调用,则 recover 的返回值保证不为 nil。为了确保这一点,使用 nil 接口值(或无类型 nil)调用 panic 会导致 *runtime.PanicNilError
类型的运行时 panic。
为了支持为旧版本 Go 编写的程序,可以通过设置 GODEBUG=panicnil=1
重新启用 nil panics。当编译其主包在声明 go
1.20
或更早版本的模块中的程序时,此设置会自动启用。
工具
Go 1.21 增加了对 Go 工具链中向后兼容性和向前兼容性的改进支持。
为了提高向后兼容性,Go 1.21 正式化了 Go 对 GODEBUG 环境变量的使用,以控制根据兼容性策略不构成破坏性更改但仍可能导致现有程序中断的更改的默认行为。(例如,依赖于错误行为的程序在错误修复时可能会中断,但错误修复不被视为破坏性更改。)当 Go 必须进行这种行为更改时,它现在根据工作区 go.work
文件或主模块 go.mod
文件中的 go
行选择旧行为和新行为。升级到新的 Go 工具链但将 go
行设置为其原始(较旧)Go 版本会保留旧工具链的行为。有了这种兼容性支持,最新的 Go 工具链应该始终是旧版本 Go 的最佳、最安全的实现。有关详细信息,请参阅“Go、向后兼容性和 GODEBUG”。
为了提高向前兼容性,Go 1.21 现在将 go.work
或 go.mod
文件中的 go
行读取为严格的最低要求:go
1.21.0
意味着工作区或模块不能与 Go 1.20 或 Go 1.21rc1 一起使用。这允许依赖于 Go 后续版本中修复的项目确保它们不与早期版本一起使用。它还为使用新 Go 功能的项目提供了更好的错误报告:当问题是需要更新的 Go 版本时,会清楚地报告该问题,而不是尝试构建代码并打印有关未解析导入或语法错误的错误。
为了更容易管理这些新的更严格的版本要求,go
命令现在不仅可以调用其自身版本中捆绑的工具链,还可以调用在 PATH 中找到或按需下载的其他 Go 工具链版本。如果 go.mod
或 go.work
go
行声明了对较新 Go 版本的最低要求,go
命令将自动查找并运行该版本。新的 toolchain
指令设置了建议使用的最低工具链,该工具链可能比严格的 go
最低要求更新。有关详细信息,请参阅“Go 工具链”。
Go 命令
-pgo
构建标志现在默认为 -pgo=auto
,并且删除了在命令行上指定单个主包的限制。如果主包目录中存在名为 default.pgo
的文件,go
命令将使用它来为构建相应程序启用配置文件引导优化。
-C
dir
标志在使用时现在必须是命令行上的第一个标志。
新的 go
test
选项 -fullpath
在测试日志消息中打印完整路径名,而不是仅打印基本名称。
go
test
-c
标志现在支持为多个包编写测试二进制文件,每个文件都写入 pkg.test
,其中 pkg
是包名。如果正在编译的多个测试包具有给定的包名,则会出错。
go
test
-o
标志现在接受目录参数,在这种情况下,测试二进制文件会写入该目录而不是当前目录。
当使用外部 (C) 链接器并启用 cgo 时,runtime/cgo
包现在作为附加依赖项提供给 Go 链接器,以确保 Go 运行时与 C 链接器添加的任何附加库兼容。
Cgo
在 import "C"
的文件中,Go 工具链现在正确报告尝试在 C 类型上声明 Go 方法的错误。
运行时
在打印非常深的堆栈时,运行时现在打印前 50 个(最内层)帧,然后是后 50 个(最外层)帧,而不是只打印前 100 个帧。这使得更容易查看深度递归堆栈是如何开始的,对于调试堆栈溢出尤其有价值。
在支持透明大页的 Linux 平台上,Go 运行时现在更明确地管理堆的哪些部分可能由大页支持。这导致内存利用率更高:小堆应该使用更少的内存(在病态情况下最多 50%),而大堆应该在堆的密集部分看到更少损坏的大页,从而将 CPU 使用率和延迟提高多达 1%。此更改的一个结果是运行时不再尝试解决特定的有问题 Linux 配置设置,这可能导致更高的内存开销。推荐的修复方法是根据GC 指南调整操作系统的大页设置。但是,也有其他解决方法。请参阅关于 max_ptes_none
的部分。
由于运行时内部垃圾收集调整,应用程序的尾部延迟可能会减少多达 40%,并且内存使用量略有减少。一些应用程序也可能会观察到吞吐量略有下降。内存使用量的减少应该与吞吐量的损失成比例,这样可以通过稍微增加 GOGC
和/或 GOMEMLIMIT
来恢复上一个版本的吞吐量/内存权衡(对延迟几乎没有变化)。
从 C 创建的线程到 Go 的调用需要一些设置来为 Go 执行做准备。在 Unix 平台上,此设置现在在同一线程的多个调用中得以保留。这显著减少了后续 C 到 Go 调用的开销,从每次调用约 1-3 微秒降至每次调用约 100-200 纳秒。
编译器
配置文件引导优化 (PGO),在 Go 1.20 中作为预览版添加,现在已可供通用使用。PGO 对生产工作负载配置文件中标识为“热点”的代码启用额外的优化。如Go 命令部分所述,对于主包目录中包含 default.pgo
配置文件的二进制文件,PGO 默认启用。性能改进因应用程序行为而异,大多数代表性 Go 程序集中的程序通过启用 PGO 获得了 2% 到 7% 的改进。有关详细文档,请参阅 PGO 用户指南。
PGO 构建现在可以对某些接口方法调用进行去虚拟化,为主常见的被调用者添加具体调用。这启用了进一步的优化,例如内联被调用者。
Go 1.21 将构建速度提高了 6%,这主要归功于使用 PGO 构建编译器本身。
汇编器
在 amd64 上,无帧的 nosplit 汇编函数不再自动标记为 NOFRAME
。相反,如果需要,必须明确指定 NOFRAME
属性,这已经是支持帧指针的其他架构上的行为。通过此更改,运行时现在为堆栈转换维护帧指针。
检查 amd64 上动态链接时 R15
不正确使用情况的验证器已得到改进。
链接器
在 windows/amd64 上,链接器(在编译器的帮助下)现在默认发出 SEH unwinding 数据,这改进了 Go 应用程序与 Windows 调试器和其他工具的集成。
在 Go 1.21 中,链接器(在编译器的帮助下)现在能够删除死的(未引用的)全局映射变量,如果变量初始化器中的条目数量足够大,并且如果初始化器表达式没有副作用。
标准库
新的 log/slog 包
新的 log/slog 包提供带有级别的结构化日志记录。结构化日志记录发出键值对,以实现对大量日志数据的快速、准确处理。该包支持与流行的日志分析工具和服务的集成。
新的 testing/slogtest 包
新的 testing/slogtest 包可以帮助验证 slog.Handler 实现。
新的 slices 包
新的 slices 包提供了许多常见的切片操作,使用适用于任何元素类型切片的泛型函数。
新的 maps 包
新的 maps 包提供了几种常见的映射操作,使用适用于任何键或元素类型映射的泛型函数。
新的 cmp 包
新的 cmp 包定义了类型约束 Ordered
和两个新的泛型函数 Less
和 Compare
,它们对有序类型很有用。
对库的微小更改
一如既往,库中进行了各种小的更改和更新,始终牢记 Go 1 的兼容性承诺。还有各种未在此处列出的性能改进。
archive/tar
由 Header.FileInfo
返回的 io/fs.FileInfo
接口的实现现在实现了调用 io/fs.FormatFileInfo
的 String
方法。
archive/zip
由 FileHeader.FileInfo
返回的 io/fs.FileInfo
接口的实现现在实现了调用 io/fs.FormatFileInfo
的 String
方法。
由 Reader.Open
返回的 io/fs.File
的 io/fs.ReadDirFile.ReadDir
方法返回的 io/fs.DirEntry
接口的实现现在实现了调用 io/fs.FormatDirEntry
的 String
方法。
bytes
Buffer
类型有两个新方法:Available
和 AvailableBuffer
。这些方法可以与 Write
方法一起使用,直接追加到 Buffer
。
context
新的 WithoutCancel
函数返回一个上下文的副本,当原始上下文被取消时,该副本不会被取消。
新的 WithDeadlineCause
和 WithTimeoutCause
函数提供了一种在截止日期或计时器到期时设置上下文取消原因的方法。原因可以通过 Cause
函数检索。
新的 AfterFunc
函数注册一个函数,以便在上下文取消后运行。
一项优化意味着调用 Background
和 TODO
并将其转换为共享类型的结果可以被认为是相等的。在以前的版本中,它们总是不同的。比较 Context
值是否相等从未得到明确定义,因此这不被视为不兼容的更改。
crypto/ecdsa
PublicKey.Equal
和 PrivateKey.Equal
现在以恒定时间执行。
crypto/elliptic
所有 Curve
方法以及 GenerateKey
、Marshal
和 Unmarshal
都已弃用。对于 ECDH 操作,应改用新的 crypto/ecdh
包。对于更低级的操作,请使用第三方模块,例如 filippo.io/nistec。
crypto/rand
crypto/rand
包现在在 NetBSD 10.0 及更高版本上使用 getrandom
系统调用。
crypto/rsa
对于 GOARCH=amd64
和 GOARCH=arm64
,私有 RSA 操作(解密和签名)的性能现在优于 Go 1.19。它在 Go 1.20 中有所退步。
由于在 PrecomputedValues
中添加了私有字段,因此即使反序列化(例如从 JSON)以前预计算的私钥,也必须调用 PrivateKey.Precompute
以获得最佳性能。
PublicKey.Equal
和 PrivateKey.Equal
现在以恒定时间执行。
GenerateMultiPrimeKey
函数和 PrecomputedValues.CRTValues
字段已弃用。PrecomputedValues.CRTValues
在调用 PrivateKey.Precompute
时仍将填充,但这些值在解密操作期间不会使用。
crypto/sha256
SHA-224 和 SHA-256 操作在 GOARCH=amd64
时现在会使用可用的原生指令,提供大约 3-4 倍的性能提升。
crypto/tls
服务器现在会跳过验证客户端证书(包括不运行 Config.VerifyPeerCertificate
),对于已恢复的连接,除了检查过期时间。这使得在使用客户端证书时会话票据更大。客户端已经跳过恢复时的验证,但即使设置了 Config.InsecureSkipVerify
,现在也会检查过期时间。
应用程序现在可以控制会话票据的内容。
- 新的
SessionState
类型描述了一个可恢复的会话。 SessionState.Bytes
方法和ParseSessionState
函数序列化和反序列化SessionState
。Config.WrapSession
和Config.UnwrapSession
钩子在服务器端将SessionState
转换为票据,反之亦然。Config.EncryptTicket
和ClientSessionState.ResumptionState
方法和NewResumptionState
函数可由ClientSessionCache
实现用于在客户端存储和恢复会话。
为了减少会话票据被用作跨连接跟踪机制的可能性,服务器现在在每次恢复时(如果支持且未禁用)都会发出新的票据,并且票据不再带有加密它们的密钥的标识符。如果向 Conn.SetSessionTicketKeys
传递大量密钥,这可能会导致显著的性能开销。
客户端和服务器现在都实现了扩展主密钥扩展 (RFC 7627)。ConnectionState.TLSUnique
的弃用已被撤销,并且现在为支持扩展主密钥的已恢复连接设置。
新的 QUICConn
类型支持 QUIC 实现,包括 0-RTT 支持。请注意,这本身并不是 QUIC 实现,并且 TLS 中仍然不支持 0-RTT。
新的 VersionName
函数返回 TLS 版本号的名称。
服务器因客户端认证失败而发送的 TLS 警报代码已得到改进。以前,这些失败总是导致“坏证书”警报。现在,某些失败将导致更合适的警报代码,如 RFC 5246 和 RFC 8446 定义。
- 对于 TLS 1.3 连接,如果服务器配置为使用 RequireAnyClientCert 或 RequireAndVerifyClientCert 要求客户端身份验证,并且客户端未提供任何证书,则服务器现在将返回“需要证书”警报。
- 如果客户端提供的证书未由服务器配置的受信任证书颁发机构集签名,服务器将返回“未知证书颁发机构”警报。
- 如果客户端提供的证书已过期或尚未生效,服务器将返回“证书过期”警报。
- 在所有其他与客户端身份验证失败相关的场景中,服务器仍返回“坏证书”。
crypto/x509
RevocationList.RevokedCertificates
已弃用,并替换为新的 RevokedCertificateEntries
字段,它是一个 RevocationListEntry
的切片。RevocationListEntry
包含 pkix.RevokedCertificate
中的所有字段,以及吊销原因代码。
名称约束现在在非叶证书上正确执行,而不是在它们表达的证书上执行。
debug/elf
新的 File.DynValue
方法可用于检索给定动态标签列出的数值。
在 DT_FLAGS_1
动态标签中允许的常量标志现在定义为 DynFlag1
类型。这些标签的名称以 DF_1
开头。
该包现在定义了常量 COMPRESS_ZSTD
。
该包现在定义了常量 R_PPC64_REL24_P9NOTOC
。
debug/pe
尝试使用 Section.Data
或通过 Section.Open
返回的读取器从包含未初始化数据的节中读取,现在会返回错误。
embed
由 FS.Open
返回的 io/fs.File
现在有一个实现了 io.ReaderAt
的 ReadAt
方法。
调用 FS.Open.Stat
将返回一个现在实现了调用 io/fs.FormatFileInfo
的 String
方法的类型。
encoding/binary
新的 NativeEndian
变量可用于使用当前机器的本机字节序在字节切片和整数之间进行转换。
errors
新的 ErrUnsupported
错误提供了一种标准化方式来指示所请求的操作可能无法执行,因为它不受支持。例如,当使用不支持硬链接的文件系统时,调用 os.Link
。
flag
新的 BoolFunc
函数和 FlagSet.BoolFunc
方法定义了一个不需要参数并在使用该标志时调用函数的标志。这类似于 Func
,但适用于布尔标志。
如果已经对同名标志调用了 Set
,则标志定义(通过 Bool
、BoolVar
、Int
、IntVar
等)将引发 panic。此更改旨在检测因初始化顺序更改导致标志操作以不同于预期顺序发生的情况。在许多情况下,此问题的解决方法是引入显式包依赖项,以在任何 Set
操作之前正确排序定义。
go/ast
新的 IsGenerated
谓词报告文件语法树是否包含通常表示该文件是由工具生成的特殊注释。
新的 File.GoVersion
字段记录了任何 //go:build
或 // +build
指令所需的最低 Go 版本。
go/build
该包现在解析文件头(在 package
声明之前)中的构建指令(以 //go:
开头的注释)。这些指令在新的 Package
字段 Directives
、TestDirectives
和 XTestDirectives
中可用。
go/build/constraint
新的 GoVersion
函数返回构建表达式所隐含的最低 Go 版本。
go/token
新的 File.Lines
方法以与 File.SetLines
接受的相同形式返回文件的行号表。
go/types
新的 Package.GoVersion
方法返回用于检查包的 Go 语言版本。
hash/maphash
hash/maphash
包现在有一个纯 Go 实现,可以通过 purego
构建标签选择。
html/template
当动作出现在 JavaScript 模板字面量中时,会返回新的错误 ErrJSTemplate
。以前会返回一个未导出的错误。
io/fs
新的 FormatFileInfo
函数返回 FileInfo
的格式化版本。新的 FormatDirEntry
函数返回 DirEntry
的格式化版本。由 ReadDir
返回的 DirEntry
实现现在实现了一个调用 FormatDirEntry
的 String
方法,DirEntry
值传递给 WalkDirFunc
也是如此。
math/big
新的 Int.Float64
方法返回多精度整数最接近的浮点值,以及任何发生的舍入指示。
net
在 Linux 上,如果内核支持多路径 TCP,net 包现在可以使用它。它默认不使用。要在客户端上可用时使用多路径 TCP,请在调用 Dialer.Dial
或 Dialer.DialContext
方法之前调用 Dialer.SetMultipathTCP
方法。要在服务器上可用时使用多路径 TCP,请在调用 ListenConfig.Listen
方法之前调用 ListenConfig.SetMultipathTCP
方法。像往常一样指定网络为 "tcp"
或 "tcp4"
或 "tcp6"
。如果内核或远程主机不支持多路径 TCP,连接将静默回退到 TCP。要测试特定连接是否正在使用多路径 TCP,请使用 TCPConn.MultipathTCP
方法。
在未来的 Go 版本中,我们可能会在支持多路径 TCP 的系统上默认启用它。
net/http
新的 ResponseController.EnableFullDuplex
方法允许服务器处理程序在写入响应的同时并发读取 HTTP/1 请求正文。通常,HTTP/1 服务器在开始写入响应之前会自动消耗任何剩余的请求正文,以避免客户端在读取响应之前尝试写入完整请求时发生死锁。EnableFullDuplex
方法会禁用此行为。
当服务器使用 HTTP 响应 HTTPS 请求时,Client
和 Transport
会返回新的 ErrSchemeMismatch
错误。
net/http 包现在支持 errors.ErrUnsupported
,即表达式 errors.Is(http.ErrNotSupported, errors.ErrUnsupported)
将返回 true。
os
程序现在可以将一个空的 time.Time
值传递给 Chtimes
函数,以使访问时间或修改时间保持不变。
在 Windows 上,File.Chdir
方法现在会将当前目录更改为文件,而不是总是返回错误。
在 Unix 系统上,如果将非阻塞描述符传递给 NewFile
,调用 File.Fd
方法现在将返回一个非阻塞描述符。以前,描述符会转换为阻塞模式。
在 Windows 上,对不存在的文件调用 Truncate
曾经会创建一个空文件。它现在返回一个错误,指示该文件不存在。
在 Windows 上,调用 TempDir
现在在可用时使用 GetTempPath2W,而不是 GetTempPathW。新行为是一种安全强化措施,可防止以 SYSTEM 权限运行的进程创建的临时文件被非 SYSTEM 进程访问。
在 Windows 上,os 包现在支持处理其名称(存储为 UTF-16)无法表示为有效 UTF-8 的文件。
在 Windows 上,Lstat
现在会解析以路径分隔符结尾的路径的符号链接,这与其在 POSIX 平台上的行为一致。
由 ReadDir
函数和 File.ReadDir
方法返回的 io/fs.DirEntry
接口的实现现在实现了一个调用 io/fs.FormatDirEntry
的 String
方法。
由 DirFS
函数返回的 io/fs.FS
接口的实现现在实现了 io/fs.ReadFileFS
和 io/fs.ReadDirFS
接口。
path/filepath
传递给 WalkDir
的函数参数的 io/fs.DirEntry
接口的实现现在实现了调用 io/fs.FormatDirEntry
的 String
方法。
reflect
在 Go 1.21 中,ValueOf
不再强制将其参数分配到堆上,允许 Value
的内容分配在堆栈上。对 Value
的大多数操作也允许底层值分配在堆栈上。
新的 Value
方法 Value.Clear
清除映射的内容或将切片的内容归零。这对应于添加到语言中的新内置函数 clear
。
SliceHeader
和 StringHeader
类型现在已弃用。在新代码中,优先使用 unsafe.Slice
、unsafe.SliceData
、unsafe.String
或 unsafe.StringData
。
regexp
Regexp
现在定义了 MarshalText
和 UnmarshalText
方法。这些方法实现了 encoding.TextMarshaler
和 encoding.TextUnmarshaler
,并将被诸如 encoding/json 等包使用。
runtime
Go 程序生成的文本堆栈跟踪,例如崩溃时、调用 runtime.Stack
或使用 debug=2
收集 goroutine 配置文件时生成的堆栈跟踪,现在包含创建堆栈跟踪中每个 goroutine 的 goroutine ID。
崩溃的 Go 应用程序现在可以通过设置环境变量 GOTRACEBACK=wer
或在崩溃前调用 debug.SetTraceback("wer")
来选择加入 Windows 错误报告 (WER)。除了启用 WER,运行时行为将与 GOTRACEBACK=crash
相同。在非 Windows 系统上,GOTRACEBACK=wer
被忽略。
GODEBUG=cgocheck=2
,一个严格的 cgo 指针传递规则检查器,不再作为调试选项提供。相反,它作为一项实验,通过 GOEXPERIMENT=cgocheck2
提供。这意味着此模式必须在构建时而不是启动时选择。
GODEBUG=cgocheck=1
仍然可用(并且仍然是默认值)。
运行时包中添加了一个新类型 Pinner
。Pinner
可用于“固定”Go 内存,以便非 Go 代码可以更自由地使用它。例如,现在允许将引用固定 Go 内存的 Go 值传递给 C 代码。以前,cgo 指针传递规则不允许传递任何此类嵌套引用。有关详细信息,请参阅文档。
runtime/metrics
一些以前内部的 GC 指标,例如活动堆大小,现在可用。GOGC
和 GOMEMLIMIT
现在也可用作指标。
runtime/trace
在 amd64 和 arm64 上收集 trace 现在产生的 CPU 开销显著降低:比上一个版本改进了多达 10 倍。
trace 现在包含 Go 运行时可能停止世界的所有原因的显式停止世界事件,而不仅仅是垃圾回收。
sync
新的 OnceFunc
、OnceValue
和 OnceValues
函数捕获了 Once 的常见用法,用于在首次使用时惰性初始化值。
syscall
在 Windows 上,Fchdir
函数现在将当前目录更改为其参数,而不是总是返回错误。
在 FreeBSD 上,SysProcAttr
有一个新字段 Jail
,可用于将新创建的进程放入监狱环境中。
在 Windows 上,syscall 包现在支持处理其名称(存储为 UTF-16)无法表示为有效 UTF-8 的文件。UTF16ToString
和 UTF16FromString
函数现在在 UTF-16 数据和 WTF-8 字符串之间进行转换。这是向后兼容的,因为 WTF-8 是早期版本中使用的 UTF-8 格式的超集。
几个错误值与新的 errors.ErrUnsupported
匹配,因此 errors.Is(err, errors.ErrUnsupported)
返回 true。
ENOSYS
ENOTSUP
EOPNOTSUPP
EPLAN9
(仅限 Plan 9)ERROR_CALL_NOT_IMPLEMENTED
(仅限 Windows)ERROR_NOT_SUPPORTED
(仅限 Windows)EWINDOWS
(仅限 Windows)
testing
新的 -test.fullpath
选项将在测试日志消息中打印完整路径名,而不是仅打印基本名称。
新的 Testing
函数报告程序是否是由 go
test
创建的测试。
testing/fstest
调用 Open.Stat
将返回一个现在实现了调用 io/fs.FormatFileInfo
的 String
方法的类型。
unicode
unicode
包和整个系统中的相关支持已升级到 Unicode 15.0.0。
移植
Darwin
如 Go 1.20 发行说明中宣布,Go 1.21 需要 macOS 10.15 Catalina 或更高版本;对先前版本的支持已停止。
Windows
如 Go 1.20 发行说明中宣布,Go 1.21 至少需要 Windows 10 或 Windows Server 2016;对先前版本的支持已停止。
ARM
当在非 ARM 系统上使用 GOARCH=arm
构建 Go 分发版时(即,当构建一个交叉编译器到 ARM 时),GOARM
环境变量的默认值现在总是设置为 7
。以前的默认值取决于构建系统的特性。
当不构建交叉编译器时,默认值由检查构建系统确定。这在 Go 1.21 之前和现在都适用。变化的是在构建交叉编译器时的行为。
WebAssembly
新的 go:wasmimport
指令现在可以在 Go 程序中用于从 WebAssembly 主机导入函数。
Go 调度器现在与 JavaScript 事件循环的交互效率更高,尤其是在频繁阻塞异步事件的应用程序中。
WebAssembly 系统接口
Go 1.21 添加了对 WebAssembly 系统接口 (WASI) 预览版 1 (GOOS=wasip1
, GOARCH=wasm
) 的实验性移植。
由于添加了新的 GOOS
值“wasip1
”,除了正在使用该 GOOS
值的情况外,Go 工具现在将忽略名为 *_wasip1.go
的 Go 文件。如果您有匹配该模式的现有文件名,则需要重命名它们。
ppc64/ppc64le
在 Linux 上,GOPPC64=power10
现在生成 PC 相对指令、前缀指令和其他新的 Power10 指令。在 AIX 上,GOPPC64=power10
生成 Power10 指令,但不生成 PC 相对指令。
当为 GOPPC64=power10
GOOS=linux
GOARCH=ppc64le
构建位置独立二进制文件时,用户在大多数情况下可以期待更小的二进制文件大小,某些情况下可减少 3.5%。位置独立二进制文件使用以下 -buildmode
值针对 ppc64le 构建:c-archive
、c-shared
、shared
、pie
、plugin
。
loong64
linux/loong64
端口现在支持 -buildmode=c-archive
、-buildmode=c-shared
和 -buildmode=pie
。