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)的泛型函数的调用,其中函数参数也可能是泛型的,并且被调用函数及其参数的类型参数是从容器类型推断出来的。更一般地,如果类型参数可以从赋值中推断出来,则现在可以在不进行显式实例化的情况下使用泛型函数,前提是将其赋值给变量或作为结果值返回。
- 类型推断现在在将值赋值给接口时也会考虑方法:可以从匹配方法的相应参数类型推断出方法签名中使用的类型参数的类型参数。
- 类似地,由于类型参数必须实现其对应约束的所有方法,因此会匹配类型参数和约束的方法,这可能导致推断出其他类型参数。
- 如果将多种不同类型的未类型常量参数(例如未类型整数和未类型浮点数常量)传递给具有相同(未其他指定)类型参数类型的参数,则现在类型推断使用与具有未类型常量操作数的操作符相同的方法确定类型,而不是报错。此更改使从未类型常量参数推断出的类型与常量表达式的类型保持一致。
- 在匹配赋值中的对应类型时,类型推断现在很精确:组件类型(例如切片的元素或函数签名中的参数类型)必须相同(给定合适的类型参数)才能匹配,否则推断失败。此更改会生成更准确的错误消息:过去,类型推断可能错误地成功并导致无效赋值,而现在如果两种类型不可能匹配,编译器会报告推断错误。
更一般地说,语言规范中对 类型推断 的描述已得到澄清。总的来说,所有这些更改使类型推断功能更强大,推断失败也更不容易让人感到意外。
Go 1.21 包含我们正在考虑用于未来 Go 版本的语言更改的预览:使 for 循环变量成为每次迭代的,而不是每个循环的,以避免意外的共享错误。有关如何尝试该语言更改的详细信息,请参阅 LoopvarExperiment wiki 页面。
Go 1.21 现在定义,如果一个 goroutine 正在发生恐慌并且 recover 被一个延迟函数直接调用,则保证 recover 的返回值不为 nil。为了确保这一点,使用 nil 接口值(或未类型 nil)调用 panic 会导致类型为 *runtime.PanicNilError
的运行时恐慌。
为了支持为旧版 Go 编写的程序,可以通过设置 GODEBUG=panicnil=1
重新启用 nil 恐慌。当编译主包位于声明 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
标志现在接受目录参数,在这种情况下,测试二进制文件将写入该目录而不是当前目录。
当启用 cgo 与外部(C)链接器一起使用时,runtime/cgo
包现在作为附加依赖项提供给 Go 链接器,以确保 Go 运行时与 C 链接器添加的任何其他库兼容。
Cgo
在导入 "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 展开数据,这改善了 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
接口的实现现在实现了 String
方法,该方法调用 io/fs.FormatFileInfo
。
archive/zip
FileHeader.FileInfo
返回的 io/fs.FileInfo
接口的实现现在实现了 String
方法,该方法调用 io/fs.FormatFileInfo
。
Reader.Open
返回的 io/fs.File
的 io/fs.ReadDirFile.ReadDir
方法返回的 io/fs.DirEntry
接口的实现现在实现了 String
方法,该方法调用 io/fs.FormatDirEntry
。
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
当 GOARCH=amd64
时,SHA-224 和 SHA-256 操作现在使用本机指令(如果可用),从而提供大约 3-4 倍的性能提升。
crypto/tls
除了检查过期时间外,服务器现在会跳过验证恢复连接的客户端证书(包括不运行 Config.VerifyPeerCertificate
)。当使用客户端证书时,这会使会话票证更大。客户端在恢复时已经跳过验证,但现在即使设置了 Config.InsecureSkipVerify
也会检查过期时间。
应用程序现在可以控制会话票证的内容。
- 新的
SessionState
类型描述了一个可恢复的会话。 SessionState.Bytes
方法和ParseSessionState
函数序列化和反序列化SessionState
。Config.WrapSession
和Config.UnwrapSession
钩子在服务器端将SessionState
转换为票证并从票证转换回来。Config.EncryptTicket
和Config.DecryptTicket
方法提供了WrapSession
和UnwrapSession
的默认实现。ClientSessionState.ResumptionState
方法和NewResumptionState
函数可供ClientSessionCache
实现使用,以在客户端存储和恢复会话。
为了减少会话票证被用作跨连接跟踪机制的可能性,服务器现在在每次恢复时(如果支持并且未禁用)都会发出新票证,并且票证不再带有加密它们的密钥的标识符。如果将大量密钥传递给 Conn.SetSessionTicketKeys
,这可能会导致明显的性能成本。
客户端和服务器现在都实现了扩展主密钥扩展 (RFC 7627)。ConnectionState.TLSUnique
的弃用已被撤消,现在已针对支持扩展主密钥的恢复连接设置。
新的 QUICConn
类型提供了对 QUIC 实现的支持,包括 0-RTT 支持。请注意,这本身不是 QUIC 实现,并且 0-RTT 仍不受 TLS 支持。
新的 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
现在具有一个 ReadAt
方法,该方法实现了 io.ReaderAt
。
调用 FS.Open.Stat
将返回一个现在实现 String
方法的类型,该方法调用 io/fs.FormatFileInfo
。
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
的实现现在实现了一个 String
方法,该方法调用 FormatDirEntry
,并且 WalkDirFunc
传递的 DirEntry
值也是如此。
math/big
新的 Int.Float64
方法返回最接近多精度整数的浮点值,以及任何发生的舍入指示。
net
在 Linux 上,当内核支持时,net 包现在可以使用多路径 TCP。默认情况下不使用它。要在客户端使用可用时的多路径 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
方法禁用此行为。
当服务器对 HTTPS 请求以 HTTP 响应进行响应时,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
接口的实现现在实现了一个 String
方法,该方法调用 io/fs.FormatDirEntry
。
DirFS
函数返回的 io/fs.FS
接口的实现现在实现了 io/fs.ReadFileFS
和 io/fs.ReadDirFS
接口。
path/filepath
传递给 WalkDir
的函数参数的 io/fs.DirEntry
接口的实现现在实现了一个 String
方法,该方法调用 io/fs.FormatDirEntry
。
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 上收集跟踪现在产生的 CPU 成本大大降低:与上一版本相比,最多提高了 10 倍。
跟踪现在包含每个 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
将返回一个现在实现String
方法的类型,该方法调用io/fs.FormatFileInfo
。
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;对以前版本的支持已停止。
WebAssembly
新的go:wasmimport
指令现在可以在 Go 程序中用于从 WebAssembly 宿主导入函数。
Go 调度程序现在与 JavaScript 事件循环的交互效率更高,尤其是在经常阻塞异步事件的应用程序中。
WebAssembly 系统接口
Go 1.21 添加了一个实验性端口到WebAssembly 系统接口 (WASI),预览版 1(GOOS=wasip1
,GOARCH=wasm
)。
由于添加了新的GOOS
值“wasip1
”,因此现在将忽略名为*_wasip1.go
的 Go 文件被 Go 工具忽略,除非正在使用该GOOS
值。如果您有与该模式匹配的现有文件名,则需要重命名它们。
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
。