文章目录
- 1.Introduction to Go 1.18
- 2.Changes to the language
- 2.1 泛型(Generics)
- 2.2 Bug 修复(Bug fixes)
- 3.Ports
- 3.1 AMD64
- 3.2 RISC-V
- 3.3 Linux
- 3.4 Windows
- 3.5 iOS
- 3.6 FreeBSD
- 4.Tools
- 4.1 模糊测试
- 4.2 Go 命令
- 4.2.1 go get
- go get
- 自动 go.mod 和 go.sum 更新
- go version
- go mod download
- go mod vendor
- go mod tidy
- go work
- go build -asan
- go test
- //go:build lines
- 4.3 Gofmt
- 4.4 Vet
- 泛型更新
- 现有检查器的精度改进
- 5.Runtime
- 6.Compiler
- 7.Linker
- 8.引导程序(Bootstrap)
- 9.Core library
- 新包 debug/buildinfo
- 新包 net/netip
- TLS 1.0 和 1.1 默认在客户端禁用
- 拒绝 SHA-1 证书
- 库的小改动
- bufio
- bytes
- crypto/elliptic
- crypto/tls
- crypto/x509
- debug/dwarf
- debug/elf
- debug/plan9obj
- embed
- go/ast
- go/constant
- go/token
- go/types
- html/template
- image/draw
- net
- net/http
- os/user
- reflect
- regexp
- runtime/debug
- runtime/pprof
- strconv
- strings
- sync
- syscall
- syscall/js
- testing
- text/template
- text/template/parse
- unicode/utf8
- 参考文献
美国时间 2022 年 3 月 15 日,Go 团队官宣 Go 1.18 正式发布。下面让我们一起了解下 Go 1.18 为我们带来的新特性吧。
本文主要翻译自 Go 1.18 Release Notes - The Go Programming Language。
1.Introduction to Go 1.18
Go 1.18 是一个重要的版本,包括对语言、工具链的实现、运行时和库的改变。Go 1.18 在 Go 1.17 发布七个月后发布,一如既往,该版本保持了 Go 1 的兼容性承诺。我们期望几乎所有的 Go 程序都能像以前一样继续编译和运行。
2.Changes to the language
2.1 泛型(Generics)
Go 1.18 包括 Type Parameters Proposal 所描述的泛型功能。这包括对语言的主要 - 但完全向后兼容的改变。
这些新的语言变化需要大量的新代码来实现,但是这些代码并没有在生产环境中进行过大量的测试,这只会随着越来越多的人编写和使用泛型代码而发生。我们相信这个功能实现得很好,质量很高。然而,与 Go 的大多数方面不同,我们无法用现实世界的经验来支持这一信念。因此,虽然我们鼓励在有意义的地方使用泛型,但在生产中部署泛型代码时请适当谨慎。
虽然我们相信新的语言特性设计得很好,而且说明得很清楚,但我们有可能犯了错误。我们想强调 Go 1 compatibility guarantee 中的描述:“如果有必要解决规范中的不一致或不完整,解决这个问题可能会影响现有程序的意义或合法性。我们保留解决此类问题的权利,包括更新实现方式”。它还说:“如果一个编译器或库有一个违反规范的 bug,如果这个 bug 被修复,一个依赖这个 bug 行为的程序可能会被破坏。我们保留修复这种错误的权利”。换句话说,有可能会有一些使用泛型的代码在 1.18 版本中可以使用,但在以后的版本中会被破坏。我们不计划也不期望做任何这样的改变。然而,在未来的版本中,由于我们今天无法预见的原因,破坏 1.18 版本的程序可能成为必要。我们将尽可能地减少任何这样的破坏,但我们不保证破坏不会发生。
以下是最明显变化的列表。如需更全面的概述,请参阅 proposal(提案)。有关详细信息,请参阅 language spec(语言规范)。
- 函数和类型声明的语法现在接受了类型参数。
- 参数化的函数和类型可以通过在它们后面加上方括号中的类型参数列表进行实例化。
- 在操作符和标点符号中加入了新的符号 ~。
- 接口类型的语法现在允许嵌入任意类型(不仅仅是接口的类型名)以及 union 和 ~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 一组泛型函数,可以对任何键或元素类型的 map 进行操作。
当前的泛型实现具有以下已知限制:
- Go 编译器无法处理泛型函数或方法中的类型声明。我们希望在未来的版本中提供对此功能的支持。
- Go 编译器不接受预先声明的函数 real、imag 和 complex 的参数类型的参数。我们希望在未来的版本中取消此限制。
- Go 编译器只支持在参数类型为 P 的值 x 上调用方法 m,如果 m 是由 P 的约束接口明确声明的。同样,方法值 x.m 和方法表达式 P.m 也只有在 P 明确声明了 m 的情况下才会被支持,尽管由于 P 中的所有类型都实现了 m,m 可能在 P 的方法集中。我们希望在未来的版本中取消此限制。
- Go 编译器不支持访问类型参数 x 的结构字段 x.f ,即使类型参数的类型集中的所有类型都有字段 f。我们可能会在未来的版本中删除此限制。
- 不允许将类型参数或指向类型参数的指针作为未命名字段嵌入到结构类型中。同样地,不允许在接口类型中嵌入类型参数。目前还不清楚此限制在未来版本是否会被允许。
- 具有多个 term 的联合元素不能包含具有非空方法集的接口类型。目前还不清楚此限制在未来版本否会被允许。
泛型也代表了 Go 生态系统的巨大变化。虽然我们更新了几个支持泛型的核心工具,但还有很多工作要做。剩余的工具、文档和库需要时间才能赶上这些语言变化。
2.2 Bug 修复(Bug fixes)
Go 1.18 编译器现在可以正确报告 declared but not used 在函数中设置但从未使用过的变量的错误。在 Go 1.18 之前,编译器不会在这种情况下报错。这修复了长期悬而未决的编译器问题 #8560。由于这一变化,(可能是不正确的)程序可能无法再编译了。必要的修正是简单直接的:如果程序确实不正确,就修正它,或者使用违规的变量,例如把它赋值给空白标识符 _。由于go vet总是指出这个错误,受影响的程序数量可能非常小。
Go 1.18 编译器现在报告说,当把 '1' << 32'
等 rune 常量表达式作为参数传给预先声明的函数 print 和 println 时,会出现溢出,这与用户定义的函数的行为保持一致。在 Go 1.18 之前,如果它们能被隐式转为 int64,编译器在这种情况下不会报错。由于此更改,(可能不正确的)程序编译不通过。必要的修复很简单:如果程序实际上不正确,则修复程序,或者将有问题的参数显式转换为正确的类型。由于 go vet 总是指出这个错误,因此受影响的程序数量可能非常少。
3.Ports
3.1 AMD64
Go 1.18 引入了新的 GOAMD64 环境变量,它在编译时选择 AMD64 架构的最低目标版本。允许的值为 v1、 v2、v3 或 v4。每个更高级别都需要并利用额外的处理器功能。可以在 此处找到详细说明。
GOAMD64 环境变量默认为 v1。
3.2 RISC-V
Linux 上的 64 位 RISC-V 架构(linux/riscv64)现在支持 c-archive 和 c-shared 构建模式。
3.3 Linux
Go 1.18 需要 Linux 内核版本 2.6.32 或更高版本。
3.4 Windows
windows/arm 和 windows/arm64 现在支持非合作性抢占,从而使所有四个 Windows端都具备了这种能力,这有望解决在调用 Win32 函数时遇到的长时间阻塞的微妙错误。
3.5 iOS
在 iOS (ios/arm64 ) 和基于 AMD64 的 macOS (ios/amd64) 上运行的 iOS 模拟器上,Go 1.18 现在需要 iOS 12 或更高版本;对以前版本的支持已经停止了。
3.6 FreeBSD
Go 1.18 是 FreeBSD 11.x 支持的最后一个版本,该版本已经结束。Go 1.19 需要 FreeBSD 12.2 或 FreeBSD 13.0 。FreeBSD 13.0 需要一个带有 COMPAT_FREEBSD12 选项集的内核(这是默认设置)。
4.Tools
4.1 模糊测试
Go 1.18 包括 fuzzing 的实现,如 fuzzing proposal 所述。
请参阅 fuzzing 登录页面以开始使用。
请注意,模糊测试会消耗大量内存,并且可能会影响机器运行时的性能。另请注意,模糊引擎在运行时会将扩展测试覆盖率的值写入模糊缓存目录 $GOCACHE/fuzz
。目前对可以写入模糊缓存的文件数量或总字节数没有限制,因此可能会占用大量存储空间(可能为数 GB)。
4.2 Go 命令
4.2.1 go get
go get
go get 不再以模块感知模式构建或安装包。go get 现在致力于调整 go.mod 中的依赖关系。实际上,-d 标志始终处于启用状态。要在当前模块的上下文之外安装最新版本的可执行文件,使用 go install example.com/cmd@latest
。可以使用任何版本查询来代替 latest。这种形式的 go install 是在 Go 1.16 中添加的,因此支持旧版本的项目可能需要同时提供 go install 和 go get 的安装说明。go get 现在在模块外使用时报告错误,因为没有 go.mod 文件需要更新。在 GOPATH 模式下(GO111MODULE=off),go get 仍然像以前一样构建和安装软件包。
自动 go.mod 和 go.sum 更新
go mod graph、go mod vendor、go mod verify 和 go mod why 子命令不再自动更新go.mod和go.sum文件。(这些文件可以通过go get、go mod tidy或go mod download明确更新)。
go version
go 命令现在会在二进制文件中嵌入版本控制信息。它包括当前签出的修订版、提交时间,以及一个指示是否存在已编辑或未跟踪文件的标志。 如果 go 命令是在 Git、Mercurial、Fossil 或 Bazaar 仓库的一个目录中调用的,并且主包和其包含的主模块在同一个仓库中,则会嵌入版本控制信息。这个信息可以用标志 -buildvcs=false 省略。
此外,go 命令还嵌入了关于构建的信息,包括构建和工具标签(用 -tags 设置),编译器、汇编器和链接器的标志(如 -gcflags),是否启用了 cgo,如果启用了,cgo 环境变量的值(如 CGO_CFLAGS)。VCS 和构建信息可以使用 go version -m <file>
或 runtime/debug.ReadBuildInfo(对于当前运行的二进制文件)或新的 debug/buildinfo 包与模块信息一起读取。
嵌入的构建信息的底层数据格式会随着新的 go 版本的发布而改变,所以旧版本的 go 可能无法处理新版本的 go 所产生的构建信息。要从用 go 1.18 构建的二进制文件中读取版本信息,请使用 go version 命令和 go 1.18 版本的 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 标志来设置输出目录。(当使用 -mod=vendor 加载软件包时,其他 go 命令仍然从模块根部的 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 标志,能够与用 Address Sanitizer(C 编译器选项 -fsanitize=address)编译的 C(或C )代码互操作。
go test
go 命令现在支持额外的命令行选项,用于上述新的模糊测试支持。
- go test 支持 -fuzz, -fuzztime 和 -fuzzminimizetime 选项。关于这些选项的文档请参见 go help testflag。
- go clean 支持 -fuzzcache 选项。文档见 go help clean。
//go:build lines
Go 1.17 引入了 //go:build lines,作为一种更易读的方式来写构建约束,而不是 // build lines。从 Go 1.17开始,gofmt 增加了//go:build lines 来匹配现有的 build lines,并保持它们的同步,而 go vet 则在它们不同步的时候进行诊断。
由于 Go 1.18 的发布标志着对 Go 1.16 的支持结束,所有支持的 Go 版本现在都能理解 //go:build lines。在 Go 1.18 中,go fix 可以删除在 go.mod 文件中声明 go 1.18 或更低版本的模块中已被淘汰的 // build lines。
更多信息,请参见 https://go.dev/design/draft-gobuild。
4.3 Gofmt
gofmt 现在同时读取和格式化输入文件,内存限制与 GOMAXPROCS。在具有多个 CPU 的机器上,gofmt 现在应该明显更快。
4.4 Vet
泛型更新
vet 工具已更新以支持泛型代码。在大多数情况下,只要在非泛型代码中用其类型集中的类型替换类型参数后,它就会报告泛型代码的错误。如以下情况,vet 会报告一个格式错误。
代码语言:javascript复制func Print[T ~int|~string](t T) {
fmt.Printf("%d", t)
}
因为它将在 Print[string] 的非泛型等价物中报告一个格式错误。
代码语言:javascript复制func PrintString(x string) {
fmt.Printf("%d", x)
}
现有检查器的精度改进
cmd/vet 检查器 copylock、printf、sortslice、testinggoroutine 和 tests 都有适度的精度改进,以处理额外的代码模式。这可能会导致现有软件包中出现新的检查错误。例如,printf检查器现在跟踪由串联字符串常量创建的格式化字符串。所以 vet 会在以下情况下报告一个错误。
代码语言:javascript复制// fmt.Printf formatting directive %d is being passed to Println.
fmt.Println("%d" ` ≡ x (mod 2)` "n", x%2)
5.Runtime
垃圾回收器现在在确定运行频率时包括垃圾回收器工作的非堆源(例如堆栈扫描)。因此,当这些来源很重要时,垃圾回收器的开销就更容易预测。对于大多数应用程序来说,这些变化可以忽略不计;然而,一些 Go 应用程序现在可能比以前使用更少的内存并花费更多时间在垃圾收集上,反之亦然。预期的解决方法是在必要时对 GOGC 在必要时进行调整。
运行时现在可以更有效地将内存返回给操作系统,并因此被调整为更积极地工作。
Go 1.17 总体上改进了堆栈跟踪中参数的格式,但对于以寄存器传递的参数可能会打印出不准确的值。Go 1.18 中对此进行了改进,在每个可能不准确的值后面打印一个问号?
内置函数 append 在决定必须分配一个新的底层数组时,现在使用了一个稍有不同的公式来增长一个切片。新的公式不太容易出现分配行为的突然转变。
6.Compiler
Go 1.17 实现了一种新的方法,即在选定的操作系统上,在 64 位 x86 架构上使用寄存器而不是堆栈传递函数参数和结果。Go 1.18 扩展了支持的平台,包括 64 位 ARM(GOARCH=arm64)、大端和小端 64 位 PowerPC(GOARCH=ppc64,ppc64le),以及所有操作系统上的 64 位 x86 架构(GOARCH=amd64)。在 64 位 ARM 和 64 位 PowerPC 系统上,基准测试显示典型的性能提升 10% 或更多。
正如 Go 1.17 发布说明中所提到的,这一变化不影响任何安全 Go 代码的功能,并且旨在对大多数汇编代码没有影响。更多细节请参见 Go 1.17 发行说明。
编译器现在可以内联包含 range 循环或标记的 for 循环的函数。
新的 -asan 编译器选项支持新的 go 命令 -asan 选项。
因为编译器的类型检查器被完全替换以支持泛型,所以现在一些错误消息可能使用与以前不同的措辞。在某些情况下,Go 1.18 之前的错误消息提供了更多详细信息,或者以更有用的方式表述。我们打算在 Go 1.19 中解决这些情况。
由于编译器中与支持泛型有关的变化,Go 1.18 的编译速度可能比 Go 1.17 的编译速度大约慢 15%。编译后的代码的执行时间不受影响。我们打算在 Go 1.19 中提高编译器的速度。
7.Linker
链接器发出的重定位要少得多。因此,大多数代码库的链接速度会更快,需要更少的内存来链接,并生成更小的二进制文件。处理 Go 二进制文件的工具应使用 Go 1.18 的 debug/gosym 包来透明地处理新旧二进制文件。
新的 -asan 链接器选项支持新的 go 命令 -asan 选项。
8.引导程序(Bootstrap)
当从源代码构建 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 中要求使用 1.17 或更高版本的引导程序,这一变化应使过渡更加顺利。详情请见 go.dev/issue/44505。
9.Core library
新包 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 前缀。
该包还定义了几个函数来创建和检查这些新类型:
- AddrFrom4
- AddrFrom16
- AddrFromSlice
- AddrPortFrom
- IPv4Unspecified
- IPv6LinkLocalAllNodes
- IPv6Unspecified
- MustParseAddr
- MustParseAddrPort
- MustParsePrefix
- ParseAddr
- ParseAddrPort
- ParsePrefix
- PrefixFrom
该 net 包包括与现有方法并行的新方法,但返回 netip.AddrPort 而不是较重的net.IP
或*net.UDPAddr
类型:
- Resolver.LookupNetIP
- UDPConn.ReadFromUDPAddrPort
- UDPConn.ReadMsgUDPAddrPort
- UDPConn.WriteToUDPAddrPort
- UDPConn.WriteMsgUDPAddrPort
新 UDPConn 方法支持无内存分配的 I/O。
旧 net 包现在还包括在现有的类型 TCPAddr/UDPAddr 和 netip.AddrPort 之间转换的函数和方法:
- TCPAddrFromAddrPort
- UDPAddrFromAddrPort
- TCPAddr.AddrPort
- UDPAddr.AddrPort
TLS 1.0 和 1.1 默认在客户端禁用
如果没有设置 Config.MinVersion,现在客户端连接默认为 TLS 1.2。任何安全的最新服务器都应该支持 TLS 1.2,而且浏览器从2020年开始就要求它。通过将 Config.MinVersion 设置为 VersionTLS10,仍然支持 TLS 1.0 和 1.1。服务器端的默认值在 TLS1.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.19 中被移除。
库的小改动
与往常一样,在考虑到 Go 1 的兼容性承诺的情况下,对库进行了各种细微的更改和更新 。
bufio
新的 Writer.AvailableBuffer 方法返回一个空的缓冲区,其容量可能不是空的,用于类似 append 的 API。在追加之后,该缓冲区可以提供给后续的 Write 调用,并可能避免任何复制。
Reader.Reset 和 Writer.Reset 方法在对空缓冲区的对象调用时,现在使用默认的缓冲区大小。
bytes
新的 Cut 函数将一个[]byte 通过分隔符切割。它可以取代并简化许多 Index、IndexByte、IndexRune 和 SplitN 的常见用法。
Trim、TrimLeft 和 TrimRight 现在是无内存分配的,特别是对于小的 ASCII 切割集,速度可提高 10 倍。
Title 函数现在已经废弃了。它不能处理 Unicode 标点符号和特定语言的大小写规则,并且被 golang.org/x/text/cases 包所取代。
crypto/elliptic
P224、P384 和 P521 曲线实现现在都由 addchain和 fiat-cryptoP224 项目生成的代码支持, 后者基于经过正式验证的算术运算模型。他们现在使用更安全的完整公式和内部 API。P-224 和 P-384 现在大约快四倍。所有特定的曲线实现现在都是恒定时间的。 P384P521
对无效曲线点进行操作( IsOnCurve 方法返回 false 且 Unmarshal 或 Curve 在有效点上操作从来不会未返回的点)一直是未定义的行为,可能导致密钥恢复攻击,现在新后端不支持。如果向 P224、P384 或 P521 方法提供了无效点 ,则该方法现在将返回一个随机点。在未来的版本中,该行为可能会更改为显式 panic。
crypto/tls
新 Conn.NetConn 方法允许访问底层 net.Conn。
crypto/x509
在 macOS 和 iOS,当使用 nil VerifyOpts.Roots 或使用从 SystemCertPool 返回的 root pool 调用 Certificate.Verify 验证证书有效性时,现在使用平台 API 验证证书有效性。
SystemCertPool 现在可在 Windows 上使用。
在 Windows、macOS 和 iOS 上,当 SystemCertPool 返回的 CertPool 有其他证书, Certificate.Verify 将执行两种验证:一种使用平台验证器 API 和系统根,另一种使用 Go 验证器和附加根,平台验证器 API 返回的链将被优先使用。
CertPool.Subjects 已弃用。在 Windows、macOS 和 iOS 上,SystemCertPool 返回的 CertPool 将返回一个池,该池不包括 Subjects 返回的切片中的系统根,因为静态列表不能恰当地表示平台策略,并且可能根本无法从平台 API 中获得。
使用依赖于 MD5 哈希(MD5WithRSA)的签名算法对证书进行签名的支持可能在 Go 1.19 中删除。
debug/dwarf
StructField 和 BasicType 结构现在都有一个 DataBitOffset 字段,该字段保存 DW_AT_data_bit_offset 属性的值(如果存在)。
debug/elf
R_PPC64_RELATIVE 常量已添加 。
debug/plan9obj
如果文件没有符号部分,则 File.Symbols 方法现在返回新的导出错误值 ErrNoSymbols 。
embed
go:embed 指令现在可以以 all: 包含名称以点或下划线开头的文件。
go/ast
根据提案 Additions to go/ast and go/token to support parameterized functions and types,对包 go/ast 进行了以下补充:
- FuncType 和 TypeSpec 节点有一个新的字段 TypeParams 来保存类型参数(如果有的话)。
- 新的表达式节点 IndexListExpr 表示具有多个索引的索引表达式,用于具有一个以上显式类型参数的函数和类型实例化。
go/constant
新方法 Kind.String 为接收者类型返回一个人类可读的名称。
go/token
根据提案 Additions to go/ast and go/token to support parameterized functions and types,新增常量 TILDE 代表 ~ 符号。
go/types
新 Config.GoVersion 字段设置接受的 Go 语言版本。
根据提案 Additions to go/types to support type parameters,为支持类型参数,在 go/types 包中增加了以下内容。
- 增加了新的 TypeParam 类型、工厂函数 NewTypeParam 和相关方法来表示类型参数。
- 新类型 TypeParamList 保存一个类型参数的列表。
- 新类型 TypeList 保存一个类型的列表。
- 新的工厂函数 NewSignatureType 分配了一个带有(receiver或函数)类型参数的签名。为了访问这些类型参数,Signature 类型有两个新方法 Signature.RecvTypeParams 和Signature.TypeParams。
- Named 类型有四个新的方法。Named.Origin 用于获取实例化类型的原始参数化类型,Named.TypeArgs 和 Named.TypeParams 用于获取实例化或参数化类型的类型参数或类型参数,Named.SetTypeParams 用于设置类型参数(例如,当导入一个命名类型时,由于可能的循环周期,命名类型的分配和类型参数的设置不能同时进行)。
- interface 类型有四个新方法。Interface.IsComparable 和 Interface.IsMethodSet 用于查询接口定义的类型集的属性,Interface.MarkImplicit 和 Interface.IsImplicit 用于设置和测试接口是否是围绕类型约束字的隐式接口。
-增加了新的类型 Union 和 Term、工厂函数 NewUnion 和 NewTerm 以及相关方法,以表示接口中的类型集。
- 新的函数 Instantiate 实例化了一个参数化的类型。
- 新的 Info.Instances map 通过新的 Instance 类型记录函数和类型实例化。
- 增加了新的 ArgumentError 类型和相关方法,以表示与类型参数有关的错误。
- 增加了新的 Context 类型和工厂函数 NewContext,以便通过新的 Config.Context 字段,在类型检查的包之间共享相同的类型实例。
谓词 AssignableTo、ConvertibleTo、Implements、Identical、IdenticalIgnoreTags 和 AssertableTo 现在也适用于属于或包含泛型接口的参数,即在 Go 代码中只能作为类型约束使用的接口。请注意,AssignableTo、ConvertibleTo、Implements 和 AssertableTo 的行为在参数为非实例化泛型的情况下是未定义的,如果第一个参数是泛型接口,AssertableTo 是未定义的。
html/template
在 range 管道内,新 {{break}}命令将提前结束循环,新 {{continue}} 命令将立即开始下一个循环迭代。
and 函数不再总是评估所有参数;它在第一个评估为假的参数之后停止评估参数。同样,or 函数现在在第一个计算结果为 true 的参数之后停止计算参数。如果有任何参数是函数调用,这会有所不同。
image/draw
当其参数实现可选的在 Go 1.17 引入的 draw.RGBA64Image 和 image.RGBA64Image 接口时,Draw 和 DrawMask 回退实现(当参数不是最常见的图像类型时使用)现在更快。
net
net.Error.Temporary 已被弃用。
net/http
在 WebAssembly 目标上,Transport 的方法字段 Dial, DialContext, DialTLS 和 DialTLSContext 如果指定用于进行 HTTP 请求,现在将被正确使用。
新 Cookie.Valid 方法报告 cookie 是否有效。
新 MaxBytesHandler 函数创建一个 Handler,这个 Handler 会使用 MaxBytesReader 包裹它的 ResponseWriter 和 Request.Body。
在查找包含非 ASCII 字符的域名时,Unicode 到 ASCII 的转换现在按照 Unicode IDNA Compatibility Processing 标准 (UTS #46) 中定义的非过渡处理完成。改变了四种不同符文的解释:ß、ς、零宽度连接符 U 200D 和零宽度非连接符 U 200C。非过渡处理与大多数应用程序和 Web 浏览器一致。
os/user
当 cgo 不可用时,User.GroupIds 使用 Go 原生实现。
reflect
新的 Value.SetIterKey 和 Value.SetIterValue 方法使用一个 map 迭代器作为源来设置一个Value。它们等同于 Value.Set(iter.Key()) 和 Value.Set(iter.Value()),但做的内存分配较少。
新的 Value.UnsafePointer 方法将 Value 的值作为一个 unsafe.Pointer 返回。这允许调用者从 Value.UnsafeAddr 和 Value.Pointer 迁移,以消除在调用点执行 uintptr 到unsafe.Pointer 转换的需要(因为 unsafe.Pointer 规则要求)。
新的 MapIter.Reset 方法改变了它的 receiver,在不同的 map 上进行迭代。使用 MapIter.Reset 可以对许多 map 进行无内存分配的迭代。
一些方法(Value.CanInt, Value.CanUint, Value.CanFloat, Value.CanComplex)被添加到 Value 中以测试转换是否安全。
Value.FieldByIndexErr 已被添加到 Value.FieldByIndex 中,以避免在通过一个指向嵌入式结构的空指针时发生 panic。
reflect.Ptr 和 reflect.PtrTo 分别被重命名为 reflect.Pointer 和 reflect.PointerTo,以便与 reflect 包的其他部分保持一致。旧名称将继续工作,但在未来的 Go 版本中会被废弃。
regexp
regexp 现在将 UTF-8 字符串的每个无效字节视为 U FFFD。
runtime/debug
BuildInfo 结构有两个新字段,包含有关如何构建二进制文件的附加信息:
- GoVersion 保存用于构建二进制文件的 Go 版本。
- Settings是BuildSettings结构的一个slice,持有描述构建过程的键/值对。
runtime/pprof
CPU 分析器现在在 Linux 上使用每线程计时器。这增加了 profile 可以观察到的最大 CPU 使用率,并减少了某些形式的偏差。
strconv
strconv.Unquote 现在拒绝 Unicode 代理一半。
strings
新的 Cut 函数将一个字符串围绕着分隔符进行切割。它可以取代并简化许多 Index、IndexByte、IndexRune 和 SplitN 的常见用法。
新的 Clone 函数复制了输入字符串,而返回的克隆字符串没有引用输入字符串的内存。
Trim、TrimLeft 和 TrimRight 现在是 0 内存分配的,特别是对于小的 ASCII 切割集,速度可提高10倍。
Title 函数现在已经废弃了。它不能处理 Unicode 标点符号和特定语言的大写规则,并且被 golang.org/x/text/cases 包所取代。
sync
新的方法 Mutex.TryLock、RWMutex.TryLock 和 RWMutex.TryRLock,将在当前未持有锁的情况下获取锁。
syscall
新的函数 SyscallN 已经引入到 Windows,允许使用任意数量的参数进行调用。因此, Syscall, Syscall6, Syscall9, Syscall12, Syscall15, 和 Syscall18 被弃用,取而代之的是SyscallN。
SysProcAttr.Pdeathsig 现在在 FreeBSD 中得到支持。
syscall/js
Wrapper 接口已被删除。
testing
增加了-run和 -bench 参数中的 / 的优先级。A/B|C/D 曾被视为 A/(B|C)/D,现在被视为 (A/B)|(C/D)。
如果 -run 选项没有选择任何 test,-count 选项将被忽略。这可能会改变现有测试的行为,在不太可能的情况下,一个测试改变了每次运行测试函数本身时的子测试集。
新的 testing.F 类型被上述新的 fuzzing 支持所使用。测试现在也支持命令行选项 -test.fuzz,-test.fuzztime 和 -test.fuzzminimizetime。
text/template
在 range 管道内,新 {{break}} 命令将提前结束循环,新 {{continue}} 命令将立即开始下一个循环迭代。
and 函数不再总是评估所有参数;它在第一个评估为假的参数之后停止评估参数。同样,or 函数现在在第一个计算结果为 true 的参数之后停止计算参数。如果任何参数是函数调用,这会有所不同。
text/template/parse
该包通过新常量 NodeBreak 和新类型 BreakNode 支持新命令 text /template 和 html/template {{break}}。同样地,通过新常量 NodeContinue 和新类型 ContinueNode 支持新命令 {{continue}}。
unicode/utf8
新 AppendRune 函数将 UTF-8 编码的 rune 追加到 []byte。
参考文献
Go 1.18 Release Notes - The Go Programming Language Go 1.18 is released! - The Go Programming Language Go 1.18 Release Note 中文版 - 技术圈