Go 1.18 发布说明

Go 1.18 简介

最新的 Go 版本 1.18 是一个重要版本,包含语言、工具链实现、运行时和库的更改。Go 1.18 在 Go 1.17 发布七个月后到来。与往常一样,该版本保持了 Go 1 兼容性承诺。我们预计几乎所有 Go 程序都将像以前一样继续编译和运行。

语言变化

泛型

Go 1.18 包含了 类型参数提案 中描述的泛型功能的实现。这包括语言的重大(但完全向后兼容)更改。

这些新的语言更改需要大量尚未在生产环境中进行大量测试的新代码。只有当更多人编写和使用泛型代码时,这种情况才会发生。我们相信此功能实现良好且质量高。然而,与 Go 的大多数方面不同,我们无法用实际经验来支持这种信念。因此,虽然我们鼓励在有意义的地方使用泛型,但在生产环境中部署泛型代码时,请谨慎使用。

虽然我们相信新的语言特性设计良好且规范清晰,但我们可能犯了错误。我们想强调的是,Go 1 兼容性保证 声明“如果需要解决规范中的不一致或不完整,解决问题可能会影响现有程序的含义或合法性。我们保留解决此类问题的权利,包括更新实现。”它还声明“如果编译器或库存在违反规范的错误,如果修复该错误,依赖于该错误行为的程序可能会中断。我们保留修复此类错误的权利。”换句话说,可能会有一些使用泛型的代码在 1.18 版本中可以工作,但在后续版本中会中断。我们不计划也不期望进行任何此类更改。然而,在未来的版本中中断 1.18 程序可能由于我们目前无法预见的原因而变得必要。我们将尽可能减少任何此类中断,但我们不能保证中断为零。

以下是最显著的更改列表。有关更全面的概述,请参阅 提案。有关详细信息,请参阅 语言规范

  • 函数类型声明 的语法现在接受 类型参数
  • 可以通过在参数化函数和类型后添加方括号中的类型参数列表来实例化它们。
  • 新标记 ~ 已添加到 运算符和标点符号 集中。
  • 接口类型 的语法现在允许嵌入任意类型(不仅仅是接口的类型名称)以及联合和 ~T 类型元素。此类接口只能用作类型约束。接口现在定义了一组类型以及一组方法。
  • 新的 预声明标识符 any 是空接口的别名。它可以用作 interface{} 的替代。
  • 新的 预声明标识符 comparable 是一个接口,表示所有可以使用 ==!= 进行比较的类型集合。它只能用作(或嵌入在)类型约束中。

有三个使用泛型的实验性包可能很有用。这些包位于 x/exp 仓库中;它们的 API 不受 Go 1 保证的覆盖,并且可能会随着我们对泛型经验的增加而更改。

golang.org/x/exp/constraints

对泛型代码有用的约束,例如 constraints.Ordered

golang.org/x/exp/slices

在任何元素类型的切片上操作的泛型函数集合。

golang.org/x/exp/maps

在任何键或元素类型的映射上操作的泛型函数集合。

当前的泛型实现有以下已知限制:

  • Go 编译器无法处理泛型函数或方法中的类型声明。我们希望在未来版本中提供对此功能的支持。
  • Go 编译器不接受带有预声明函数 realimagcomplex 的类型参数类型的参数。我们希望在未来版本中消除此限制。
  • Go 编译器仅支持在类型参数类型 P 的值 x 上调用方法 m,如果 mP 的约束接口显式声明。类似地,方法值 x.m 和方法表达式 P.m 也仅在 mP 显式声明时才受支持,即使 m 可能是 P 的方法集中的成员,因为 P 中的所有类型都实现了 m。我们希望在未来版本中消除此限制。
  • Go 编译器不支持访问结构字段 x.f,其中 x 是类型参数类型,即使类型参数类型集中的所有类型都具有字段 f。我们可能会在未来版本中消除此限制。
  • 不允许将类型参数或指向类型参数的指针作为未命名字段嵌入到结构类型中。类似地,不允许将类型参数嵌入到接口类型中。目前尚不清楚是否会允许这些操作。
  • 具有多个项的联合元素可能不包含具有非空方法集的接口类型。目前尚不清楚是否会允许此操作。

泛型也代表着 Go 生态系统的一次重大变革。虽然我们已经更新了几个核心工具以支持泛型,但还有很多工作要做。其余工具、文档和库需要时间来跟上这些语言更改。

Bug 修复

Go 1.18 编译器现在会正确报告函数文字内部设置但从未使用过的变量的 declared but not used 错误。在 Go 1.18 之前,编译器在这种情况下不会报告错误。这修复了长期存在的编译器问题 #8560。由于此更改,(可能不正确的)程序可能无法再编译。必要的修复很简单:如果程序确实不正确,则修复它,或者使用有问题的变量,例如将其分配给空白标识符 _。由于 go vet 总是指出此错误,受影响的程序数量可能非常少。

Go 1.18 编译器现在在将 rune 常量表达式(例如 '1' << 32)作为参数传递给预声明函数 printprintln 时报告溢出,这与用户定义函数的行为一致。在 Go 1.18 之前,编译器在这种情况下不会报告错误,而是静默接受此类常量参数,如果它们适合 int64。由于此更改,(可能不正确的)程序可能无法再编译。必要的修复很简单:如果程序确实不正确,则修复它,或者将有问题的参数显式转换为正确的类型。由于 go vet 总是指出此错误,受影响的程序数量可能非常少。

移植

AMD64

Go 1.18 引入了新的 GOAMD64 环境变量,该变量在编译时选择 AMD64 架构的最小目标版本。允许的值为 v1v2v3v4。每个更高级别都需要并利用额外的处理器功能。详细说明可以在 此处 找到。

GOAMD64 环境变量默认为 v1

RISC-V

Linux 上的 64 位 RISC-V 架构(linux/riscv64 端口)现在支持 c-archivec-shared 构建模式。

Linux

Go 1.18 需要 Linux 内核版本 2.6.32 或更高版本。

Windows

windows/armwindows/arm64 端口现在支持非协作抢占,将该功能引入所有四个 Windows 端口,这有望解决在调用长时间阻塞的 Win32 函数时遇到的微妙错误。

iOS

在 iOS(ios/arm64 端口)和运行在 AMD64-based macOS 上的 iOS 模拟器(ios/amd64 端口)上,Go 1.18 现在需要 iOS 12 或更高版本;对先前版本的支持已停止。

FreeBSD

Go 1.18 是最后一个支持 FreeBSD 11.x 的版本,该版本已达到生命周期结束。Go 1.19 将需要 FreeBSD 12.2+ 或 FreeBSD 13.0+。FreeBSD 13.0+ 将需要设置了 COMPAT_FREEBSD12 选项的内核(这是默认设置)。

工具

模糊测试

Go 1.18 包含了 模糊测试提案 中描述的模糊测试实现。

请参阅 模糊测试登陆页面 以开始使用。

请注意,模糊测试会消耗大量内存,并可能在运行时影响您的机器性能。另请注意,模糊测试引擎在运行时会将扩展测试覆盖率的值写入 $GOCACHE/fuzz 中的模糊测试缓存目录。目前对模糊测试缓存中可以写入的文件数量或总字节数没有限制,因此它可能会占用大量存储空间(可能达到几个 GB)。

Go 命令

go get

go get 在模块感知模式下不再构建或安装包。go get 现在专门用于调整 go.mod 中的依赖项。实际上,-d 标志始终启用。要在当前模块上下文之外安装可执行文件的最新版本,请使用 go install example.com/cmd@latest。任何 版本查询 都可以代替 latest。这种形式的 go install 是在 Go 1.16 中添加的,因此支持旧版本的项目可能需要提供 go installgo get 的安装说明。当在模块外部使用时,go get 现在会报告错误,因为没有 go.mod 文件可供更新。在 GOPATH 模式下(使用 GO111MODULE=off),go get 仍然像以前一样构建和安装包。

自动 go.modgo.sum 更新

go mod graphgo mod vendorgo mod verifygo mod why 子命令不再自动更新 go.modgo.sum 文件。(这些文件可以使用 go getgo mod tidygo mod download 显式更新。)

go version

go 命令现在将版本控制信息嵌入到二进制文件中。它包括当前检出的修订版、提交时间以及一个标志,指示是否存在已编辑或未跟踪的文件。如果 go 命令是在 Git、Mercurial、Fossil 或 Bazaar 仓库内的目录中调用的,并且 main 包及其包含的主模块位于同一仓库中,则会嵌入版本控制信息。此信息可以使用 -buildvcs=false 标志省略。

此外,go 命令还嵌入了有关构建的信息,包括构建和工具标签(使用 -tags 设置)、编译器、汇编器和链接器标志(如 -gcflags)、cgo 是否启用,如果启用,cgo 环境变量(如 CGO_CFLAGS)的值。VCS 和构建信息都可以与模块信息一起使用 go version -m fileruntime/debug.ReadBuildInfo(对于当前运行的二进制文件)或新的 debug/buildinfo 包读取。

嵌入式构建信息的底层数据格式可能会随 Go 新版本而变化,因此较旧版本的 go 可能无法处理由较新版本 go 生成的构建信息。要从用 go 1.18 构建的二进制文件中读取版本信息,请使用 go 1.18+ 中的 go version 命令和 debug/buildinfo 包。

go mod download

如果主模块的 go.mod 文件指定 go 1.17 或更高版本,则不带参数的 go mod download 现在仅下载主模块 go.mod 文件中显式 所需 模块的源代码。(在 go 1.17 或更高版本的模块中,该集合已经包含构建主模块中的包和测试所需的所有依赖项。)要同时下载传递依赖项的源代码,请使用 go mod download all

go mod vendor

go mod vendor 子命令现在支持 -o 标志来设置输出目录。(其他 go 命令在使用 -mod=vendor 加载包时仍从模块根目录的 vendor 目录读取,因此此标志的主要用途是用于需要收集包源代码的第三方工具。)

go mod tidy

go mod tidy 命令现在会在 go.sum 文件中保留额外的校验和,用于验证 构建列表 中每个导入的包是否仅由一个模块提供所需的模块源代码。因为这种情况很少见,而且未能应用会导致构建错误,所以此更改 受主模块 go.mod 文件中的 go 版本限制。

go work

go 命令现在支持“工作区”模式。如果在工作目录或父目录中找到 go.work 文件,或者使用 GOWORK 环境变量指定了文件,它将使 go 命令进入工作区模式。在工作区模式下,将使用 go.work 文件来确定用作模块解析根的主模块集,而不是使用通常找到的 go.mod 文件来指定单个主模块。有关更多信息,请参阅 go work 文档。

go build -asan

go build 命令和相关命令现在支持 -asan 标志,该标志启用与使用地址清理器编译的 C(或 C++)代码(C 编译器选项 -fsanitize=address)的互操作。

go test

go 命令现在支持上述新 模糊测试支持 的附加命令行选项

  • go test 支持 -fuzz-fuzztime-fuzzminimizetime 选项。有关这些选项的文档,请参阅 go help testflag
  • go clean 支持 -fuzzcache 选项。有关文档,请参阅 go help clean

//go:build

Go 1.17 引入了 //go:build 行,作为编写构建约束的一种更具可读性的方式,而不是 // +build 行。从 Go 1.17 开始,gofmt 会添加 //go:build 行以匹配现有的 +build 行并保持同步,而 go vet 会诊断它们不同步的情况。

由于 Go 1.18 版本的发布标志着对 Go 1.16 支持的结束,所有受支持的 Go 版本现在都理解 //go:build 行。在 Go 1.18 中,go fix 现在会删除在其 go.mod 文件中声明 go 1.18 或更高版本的模块中现已过时的 // +build 行。

有关更多信息,请参阅 go.dev/design/draft-gobuild

Gofmt

gofmt 现在并发读取和格式化输入文件,内存限制与 GOMAXPROCS 成比例。在多 CPU 机器上,gofmt 现在应该明显更快。

Vet

泛型更新

vet 工具已更新以支持泛型代码。在大多数情况下,只要在将类型参数替换为其 类型集 中的类型后,它会在等效的非泛型代码中报告错误,它就会在泛型代码中报告错误。例如,vet 会报告以下格式错误:

func Print[T ~int|~string](t T) {
    fmt.Printf("%d", t)
}

因为它会在 Print[string] 的非泛型等效代码中报告格式错误。

func PrintString(x string) {
    fmt.Printf("%d", x)
}

现有检查器的精度改进

cmd/vet 检查器 copylockprintfsortslicetestinggoroutinetests 都已获得适度的精度改进,以处理额外的代码模式。这可能会导致现有包中报告新的错误。例如,printf 检查器现在会跟踪通过连接字符串常量创建的格式字符串。因此 vet 将在以下代码中报告错误:

  // fmt.Printf formatting directive %d is being passed to Println.
  fmt.Println("%d"+` ≡ x (mod 2)`+"\n", x%2)

运行时

垃圾收集器现在在确定运行频率时包含非堆垃圾收集器工作源(例如,堆栈扫描)。因此,当这些源很重要时,垃圾收集器开销更具可预测性。对于大多数应用程序,这些更改可以忽略不计;但是,一些 Go 应用程序现在可能比以前使用更少的内存并花费更多时间进行垃圾收集,反之亦然。预期的解决方法是在必要时调整 GOGC

运行时现在更有效地将内存返回给操作系统,并且因此进行了更积极的调整。

Go 1.17 通常改进了堆栈跟踪中参数的格式,但可能会打印寄存器中传递的参数的不准确值。Go 1.18 通过在每个可能不准确的值后面打印问号 (?) 来改进这一点。

内置函数 append 在必须分配新的底层数组时,在决定切片增长多少时使用略有不同的公式。新公式不太容易出现分配行为的突然转变。

编译器

Go 1.17 实现 了一种新的方法,在某些操作系统上使用寄存器而不是堆栈传递函数参数和结果,用于 64 位 x86 架构。Go 1.18 将支持的平台扩展到包括 64 位 ARM (GOARCH=arm64)、大端和小端 64 位 PowerPC (GOARCH=ppc64ppc64le),以及所有操作系统上的 64 位 x86 架构 (GOARCH=amd64)。在 64 位 ARM 和 64 位 PowerPC 系统上,基准测试显示典型性能提升 10% 或更多。

如 Go 1.17 发布说明中 所述,此更改不影响任何安全 Go 代码的功能,旨在对大多数汇编代码没有影响。有关更多详细信息,请参阅 Go 1.17 发布说明

编译器现在可以内联包含范围循环或带标签的 for 循环的函数。

新的 -asan 编译器选项支持新的 go 命令 -asan 选项。

由于编译器类型检查器已完全替换以支持泛型,因此某些错误消息现在可能使用与以前不同的措辞。在某些情况下,Go 1.18 之前的错误消息提供了更多详细信息或措辞更具帮助性。我们打算在 Go 1.19 中解决这些情况。

由于编译器中与支持泛型相关的更改,Go 1.18 编译速度可能比 Go 1.17 编译速度慢大约 15%。编译代码的执行时间不受影响。我们打算在未来版本中提高编译器的速度。

链接器

链接器发出的 重定位量大大减少。因此,大多数代码库链接速度更快,链接所需内存更少,并生成更小的二进制文件。处理 Go 二进制文件的工具应使用 Go 1.18 的 debug/gosym 包来透明地处理旧的和新的二进制文件。

新的 -asan 链接器选项支持新的 go 命令 -asan 选项。

引导

从源代码构建 Go 版本时,如果未设置 GOROOT_BOOTSTRAP,则 Go 的早期版本会在 $HOME/go1.4 目录(Windows 上为 %HOMEDRIVE%%HOMEPATH%\go1.4)中查找 Go 1.4 或更高版本的引导工具链。Go 现在首先查找 $HOME/go1.17$HOME/sdk/go1.17,然后才回退到 $HOME/go1.4。我们打算让 Go 1.19 要求 Go 1.17 或更高版本进行引导,此更改应该使过渡更顺畅。有关更多详细信息,请参阅 go.dev/issue/44505

标准库

新的 debug/buildinfo

新的 debug/buildinfo 包提供对 go 命令构建的可执行文件中嵌入的模块版本、版本控制信息和构建标志的访问。相同的信息也可以通过 runtime/debug.ReadBuildInfo(对于当前运行的二进制文件)和命令行上的 go version -m 获得。

新的 net/netip

新的 net/netip 包定义了一个新的 IP 地址类型 Addr。与现有的 net.IP 类型相比,netip.Addr 类型占用内存更少,是不可变的,并且可比较,因此它支持 == 并可以用作映射键。

除了 Addr,该包还定义了 AddrPort(表示 IP 和端口)和 Prefix(表示网络 CIDR 前缀)。

该包还定义了几个函数来创建和检查这些新类型:AddrFrom4AddrFrom16AddrFromSliceAddrPortFromIPv4UnspecifiedIPv6LinkLocalAllNodesIPv6UnspecifiedMustParseAddrMustParseAddrPortMustParsePrefixParseAddrParseAddrPortParsePrefixPrefixFrom

net 包包含新的方法,这些方法与现有方法并行,但返回 netip.AddrPort 而不是更重量级的 net.IP*net.UDPAddr 类型:Resolver.LookupNetIPUDPConn.ReadFromUDPAddrPortUDPConn.ReadMsgUDPAddrPortUDPConn.WriteToUDPAddrPortUDPConn.WriteMsgUDPAddrPort。新的 UDPConn 方法支持无分配 I/O。

net 包现在还包括在现有 TCPAddr/UDPAddr 类型和 netip.AddrPort 之间进行转换的函数和方法:TCPAddrFromAddrPortUDPAddrFromAddrPortTCPAddr.AddrPort客户端默认禁用 TLS 1.0 和 1.1

如果未设置 Config.MinVersion,则对于客户端连接,它现在默认为 TLS 1.2。任何安全更新的服务器都应支持 TLS 1.2,并且自 2020 年以来浏览器已要求使用它。通过将 Config.MinVersion 设置为 VersionTLS10,仍然支持 TLS 1.0 和 1.1。服务器端默认值保持不变为 TLS 1.0。

可以通过设置 GODEBUG=tls10default=1 环境变量暂时将默认值恢复为 TLS 1.0。此选项将在 Go 1.19 中删除。

拒绝 SHA-1 证书

crypto/x509 现在将拒绝使用 SHA-1 哈希函数签名的证书。这不适用于自签名根证书。自 2017 年以来,针对 SHA-1 的实际攻击 已得到证实,并且自 2015 年以来,公开受信任的证书颁发机构未颁发 SHA-1 证书。

可以通过设置 GODEBUG=x509sha1=1 环境变量暂时恢复此功能。此选项将在未来版本中删除。

对库的微小更改

与往常一样,库中有各种微小的更改和更新,这些都是在遵守 Go 1 兼容性承诺的前提下进行的。

bufio

新的 Writer.AvailableBuffer 方法返回一个空缓冲区,该缓冲区可能具有非空容量,用于 append-like API。追加后,可以将缓冲区提供给后续的 Write 调用,并可能避免任何复制。

在对具有 nil 缓冲区的对象调用时,Reader.ResetWriter.Reset 方法现在使用默认缓冲区大小。

bytes

新的 Cut 函数围绕分隔符切割 []byte。它可以替换和简化许多常见的 IndexIndexByteIndexRuneSplitN 用法。

TrimTrimLeftTrimRight 现在无分配,尤其对于小的 ASCII 剪切集,速度提高了 10 倍。

Title 函数现已弃用。它不处理 Unicode 标点符号和特定语言的字母大写规则,并已被 golang.org/x/text/cases 包取代。

crypto/elliptic

P224P384P521 曲线实现现在都由 addchainfiat-crypto 项目生成的代码支持,后者基于经过形式化验证的算术运算模型。它们现在使用更安全的完整公式和内部 API。P-224 和 P-384 现在大约快四倍。所有特定的曲线实现现在都是恒定时间的。

对无效曲线点(即 IsOnCurve 方法返回 false,且从未由 Unmarshal 或对有效点操作的 Curve 方法返回的点)进行操作一直是未定义的行为,可能导致密钥恢复攻击,并且新后端现在不支持。如果向 P224P384P521 方法提供无效点,该方法现在将返回一个随机点。此行为在未来版本中可能会更改为显式 panic。

crypto/tls

新的 Conn.NetConn 方法允许访问底层的 net.Conn

crypto/x509

当使用 nil VerifyOpts.Roots 调用 Certificate.Verify 或使用从 SystemCertPool 返回的根池时,它现在在 macOS 和 iOS 上使用平台 API 验证证书有效性。

SystemCertPool 现在可在 Windows 上使用。

在 Windows、macOS 和 iOS 上,当 SystemCertPool 返回的 CertPool 添加了额外的证书时,Certificate.Verify 将进行两次验证:一次使用平台验证器 API 和系统根,另一次使用 Go 验证器和额外的根。平台验证器 API 返回的链将优先。

CertPool.Subjects 已弃用。在 Windows、macOS 和 iOS 上,由 SystemCertPool 返回的 CertPool 将返回一个不包含 Subjects 返回的切片中的系统根的池,因为静态列表无法适当表示平台策略,并且可能根本无法从平台 API 获取。

Go 1.19 中可能会删除对使用依赖于 MD5 哈希(MD5WithRSA)的签名算法签署证书的支持。

debug/dwarf

StructFieldBasicType 结构体现在都有一个 DataBitOffset 字段,该字段保存 DW_AT_data_bit_offset 属性的值(如果存在)。

debug/elf

已添加 R_PPC64_RELATIVE 常量。

debug/plan9obj

如果文件没有符号节,File.Symbols 方法现在返回新的导出错误值 ErrNoSymbols

embed

go:embed 指令现在可以以 all: 开头,以包含名称以点或下划线开头的文件。

go/ast

根据提案 向 go/ast 和 go/token 添加支持参数化函数和类型的功能,对 go/ast 包进行了以下添加:

  • FuncTypeTypeSpec 节点有一个新的字段 TypeParams 用于保存类型参数(如果有)。
  • 新的表达式节点 IndexListExpr 表示具有多个索引的索引表达式,用于具有多个显式类型参数的函数和类型实例化。

go/constant

新的 Kind.String 方法返回接收器类型的可读名称。

go/token

根据提案 向 go/ast 和 go/token 添加支持参数化函数和类型的功能,新的常量 TILDE 表示 ~ 标记。

go/types

新的 Config.GoVersion 字段设置接受的 Go 语言版本。

根据提案 向 go/types 添加支持类型参数的功能,对 go/types 包进行了以下添加:

谓词 AssignableToConvertibleToImplementsIdenticalIdenticalIgnoreTagsAssertableTo 现在也适用于是或包含泛型接口的参数,即只能在 Go 代码中用作类型约束的接口。请注意,对于未实例化的泛型类型参数,AssignableToConvertibleToImplementsAssertableTo 的行为是未定义的,并且如果第一个参数是泛型接口,则 AssertableTo 是未定义的。

html/template

range 管道中,新的 {{break}} 命令将提前结束循环,新的 {{continue}} 命令将立即开始下一次循环迭代。

and 函数不再总是评估所有参数;它在第一个评估为 false 的参数之后停止评估参数。类似地,or 函数现在在第一个评估为 true 的参数之后停止评估参数。如果任何参数是函数调用,这会产生影响。

image/draw

当参数不是最常见的图像类型时,DrawDrawMask 回退实现(用于这种情况)现在更快,如果这些参数实现了 Go 1.17 中添加的可选 draw.RGBA64Imageimage.RGBA64Image 接口。

net

net.Error.Temporary 已弃用。

net/http

在 WebAssembly 目标上,Transport 中的 DialDialContextDialTLSDialTLSContext 方法字段现在将被正确使用,如果指定,用于发出 HTTP 请求。

新的 Cookie.Valid 方法报告 cookie 是否有效。

新的 MaxBytesHandler 函数创建一个 Handler,该 Handler 将其 ResponseWriterRequest.Body 包装在 MaxBytesReader 中。

在查找包含非 ASCII 字符的域名时,Unicode 到 ASCII 的转换现在根据 Unicode IDNA 兼容性处理 标准 (UTS #46) 中定义的非过渡处理进行。四个不同的 rune 的解释发生了变化:ß、ς、零宽度连接符 U+200D 和零宽度非连接符 U+200C。非过渡处理与大多数应用程序和 Web 浏览器保持一致。

os/user

当 cgo 不可用时,User.GroupIds 现在使用 Go 原生实现。

reflect

新的 Value.SetIterKeyValue.SetIterValue 方法使用映射迭代器作为源设置 Value。它们等效于 Value.Set(iter.Key())Value.Set(iter.Value()),但分配更少。

新的 Value.UnsafePointer 方法以 unsafe.Pointer 的形式返回 Value 的值。这允许调用者从 Value.UnsafeAddrValue.Pointer 迁移,以消除在调用点执行 uintptr 到 unsafe.Pointer 转换的需要(如 unsafe.Pointer 规则所要求)。

新的 MapIter.Reset 方法更改其接收器以迭代不同的映射。使用 MapIter.Reset 允许对许多映射进行无分配迭代。

已向 Value 添加了许多方法(Value.CanIntValue.CanUintValue.CanFloatValue.CanComplex)以测试转换是否安全。

已添加 Value.FieldByIndexErr 以避免在通过 nil 指针步进到嵌入式结构体时 Value.FieldByIndex 中发生的 panic。

reflect.Ptrreflect.PtrTo 已分别重命名为 reflect.Pointerreflect.PointerTo,以与 reflect 包的其余部分保持一致。旧名称将继续有效,但在未来的 Go 版本中将被弃用。

regexp

regexp 现在将 UTF-8 字符串的每个无效字节视为 U+FFFD

runtime/debug

BuildInfo 结构体有两个新字段,包含有关二进制文件如何构建的额外信息:

runtime/pprof

CPU 性能分析器现在在 Linux 上使用每线程计时器。这增加了性能分析可观察到的最大 CPU 使用率,并减少了某些形式的偏差。

strconv

strconv.Unquote 现在拒绝 Unicode 代理对。

strings

新的 Cut 函数围绕分隔符切割 string。它可以替换和简化许多常见的 IndexIndexByteIndexRuneSplitN 用法。

新的 Clone 函数复制输入 string,而返回的克隆 string 不引用输入字符串的内存。

TrimTrimLeftTrimRight 现在无分配,尤其对于小的 ASCII 剪切集,速度提高了 10 倍。

Title 函数现已弃用。它不处理 Unicode 标点符号和特定语言的字母大写规则,并已被 golang.org/x/text/cases 包取代。

sync

新的方法 Mutex.TryLockRWMutex.TryLockRWMutex.TryRLock 将在当前未持有时获取锁。

syscall

为 Windows 引入了新函数 SyscallN,允许调用任意数量的参数。因此,SyscallSyscall6Syscall9Syscall12Syscall15Syscall18 已弃用,转而使用 SyscallN

FreeBSD 现在支持 SysProcAttr.Pdeathsig

syscall/js

Wrapper 接口已被移除。

testing

-run-bench 参数中 / 的优先级已提高。A/B|C/D 以前被视为 A/(B|C)/D,现在被视为 (A/B)|(C/D)

如果 -run 选项没有选择任何测试,则忽略 -count 选项。这可能会在测试每次运行时更改子测试集的情况下,改变现有测试的行为(尽管这种情况不太可能发生)。

新的 testing.F 类型由上述新 模糊测试支持 使用。测试现在还支持命令行选项 -test.fuzz-test.fuzztime-test.fuzzminimizetime

text/template

range 管道中,新的 {{break}} 命令将提前结束循环,新的 {{continue}} 命令将立即开始下一次循环迭代。

and 函数不再总是评估所有参数;它在第一个评估为 false 的参数之后停止评估参数。类似地,or 函数现在在第一个评估为 true 的参数之后停止评估参数。如果任何参数是函数调用,这会产生影响。

text/template/parse

该包通过新常量 NodeBreak 和新类型 BreakNode 支持新的 text/templatehtml/template {{break}} 命令,并通过新常量 NodeContinue 和新类型 ContinueNode 支持新的 {{continue}} 命令。

unicode/utf8

新的 AppendRune 函数将 rune 的 UTF-8 编码附加到 []byte