【官方发布说明】Go 1.18正式发布

Go 1.18 发布说明


介绍 Go 1.18

0eaf3b1ac19bb702d6a815d774b64cb2.png

Go最新release,版本1.18,是一个重大的release,包含了语言上的改变,工具链、runtime和库的实现。Go 1.18在Go 1.17发布7个月之后到来。和往常一样,考虑到了Go 1的兼容性承诺。我们希望所有的Go程序可以向之前一样继续编译和运行。


Go语言的变化

03c03109cac8f7719a6d79e3d9c78fd5.png

泛型

Go 1.18包含一个在类型参数提案中描述的泛型特性的实现,这包括对语言的重大–但完全向后兼容的–改变。

这些新的变化需要编写大量新的代码,然而这些代码还没有在生产环境中进行过大量的测试。这只会在当越来越多人编写和使用泛型的时候才会发生。我们相信这些新特性的实现是优雅的,并且是高质量的。然而,与Go大多数方面不同的是,我们无法用现实世界的经验来支持这种信念。因此,虽然我们鼓励在某些需要使用的泛型的场景下使用泛型,但当部署泛型代码到生产环境时,请多谨慎一些。

虽然我们相信新的语言功能设计得很好,而且规定得很清楚,但我们有可能犯了错误。我们想要强调的是Go 1 兼容保证上说 “如果有必要解决规范中的不一致或不完整,但是解决这个问题可能会影响现有程序的意义或合法性。那我们保留解决此类问题的权利,包括更新实施。”它也陈述了“如果一个编译器或库有一个违反规范的bug,那么如果这个bug被修复,依赖于这个bug行为的程序可能会被破坏。我们保留修复此类bug的权利。”换句话说,有可能会有一些使用泛型的代码在1.18版本中可以使用,但在以后的版本中会出现问题。我们不计划也不期望做出任何此类改变。然而,在未来的版本中,由于我们今天无法预见的原因,调整1.18的程序可能成为必要。我们将尽可能地减少任何此类调整变动,但我们不能保证变动的几率为零。

以下是最明显的变化列表。关于更全面的概述,请看提案。详情见语言规范。

  • 函数和类型宣告的语法,现在接受类型参数。

  • 参数化的函数和类型可以通过在它们后面加上类型参数列表来进行实例化,类型参数列表放在方括号中。

  • 添加了新的标识 ~ 到运算符和标点符号。

  • 接口类型的语法现在已经支持嵌套任意类型(不只是接口的类型名称),以及union和 ~T 类型元素。这样的接口只能作为类型约束使用。现在一个接口定义了一组类型以及一组方法。

  • 新的提前宣告标识符(prdeclared identifyer) any 作为空接口的别名。这将取代原有的 interface{}

  • 新的提前宣告标识符(prdeclared identifyer) comparable 是一个接口表示所有可以通过==或者!=来比较的类型的集合。它只能用于(或者嵌套)一个类型约束。有三个使用泛型实现的实验性质的包可能会有用。这些包在 x/exp仓库;它们的API不在Go的保证范围内,而且随着我们对泛型经验的增加,可能会发生变化。

goland.org/x/exp/constraints

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

golang.org/x/exp/slices

一个泛型函数的集合,可以对任何元素类型的切片进行操作。

golang.org/x/exp/maps

一个泛型函数的集合,可以对任何键或元素类型的map进行操作。

现在泛型的实现还有如下的限制:

  • Go编译器目前不能处理泛型函数或者方法内的类型声明。我们希望在Go 1.19提供这个特性。

  • Go编译器目前在预先声明函数的参数类型上不支持realimagcomplex类型。我们希望在Go 1.19移除这个限制。

  • 如果m是由P的约束接口明确声明的,那Go编译器目前只支持在参数类型为P的值x上调用方法m。同样的,只在m是由P的约束接口明确声明的,才支持方法值x.m和方法表达式P.m, 即使由于P中的所有类型都实现了m,导致m在P的方法集中也不能支持上述的使用方式。我们希望在Go 1.19移除这个限制。

  • 不允许将类型参数或指向类型参数的指针作为结构类型中的未命名字段嵌入。同样的,不允许将类型参数嵌入到一个接口类型。这个是否会被允许,目前还是未知的。

  • 有一个以上元素的集合元素不能包含一个具有非空方法集的接口类型。这个是否会被允许,目前还是未知的。泛型也代表着Go生态系统会有大量的变动。虽然我们已经更新了一些核心工具来对泛型做支持,但是还有很多许需要去做的。剩下的工具、文档和库需要时间来赶上这些语言发生的变化。

Bug修复

Go 1.18 编译器现在可以正确报告在函数字面中设置,但从未使用的变量的声明错误。在Go 1.18之前,编译器在这种情况下不会报告错误。这修复了长期存在的编译器问题。由于这一变化,(可能是不正确的)程序可能不再被编译。可以直接这么修改:如果程序实际上是不正确的,就修复它,或者使用了违规的变量,例如把它赋值给空白标识符_。由于go vet总是指出这个错误,受影响的程序数量可能非常少。

当将一个符文常量表达式,例如'1' << 32,作为一个参数传递给预先声明函数printpintln 时,Go 1.18编译器会报告溢出,与用户定义的函数的行为一致。在Go 1.18之前,编译器对此情况不是报错误,而是如果它符合int64的要求,就会接收它。由于这一变化,(可能是不正确的)程序可能不再被编译。可以直接这么修改:如果程序实际上是不正确的,就修复它,或者使用了违规的变量,例如把它赋值给空白标识符_。由于go vet总是指出这个错误,受影响的程序数量可能非常少。


Ports

597edaf0aff7b93f8c537dabc7db5e85.png

AMD64

Go 1.18介绍了新的环境变量GOAMD64,它在编译时选择了AMD64架构的最小目标版本。允许的值是v1v2v3,或者v4。每一个更高的级别都需要并利用额外的处理器功能。详细的描述可以在这里找到。

GOAMD64环境变量默认是v1

RISC-V

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

Linux

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

Windows

windows/arm and windows/arm64 ports现在支持非合作式抢占,从而使所有四个 Windows ports都具备了这种能力,这有望解决在调用 Win32 函数时遇到的长时间阻塞的微妙错误。

iOS

在iOS(ios/arm64 port)和基于AMD64的macOS(ios/amd64 port)上运行的iOS模拟器上,Go 1.18现在需要iOS 12或更高版本;对以前版本的支持已经停止了。

FreeBSD

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


工具

594ebb97fc48397d2c9fb461d85b478b.png

Fuzzing

Go 1.18包含了the fuzzing提案描述的fuzzing的实现。

详见fuzzing landing page开始使用。

请注意的是fuzzing会消耗大量的内存,并且在运行时有可能会影响你机器的性能。还要注意的是,fuzzing引擎在运行时,会将扩大测试范围的数值写入$GOCACHE/fuzz内的fuzzing缓存目录,目前没有限制写入fuzzing缓存的文件数量或者写入的字节总数,所以它可能会占用大量的存储(有可能几个GBs)。

Go指令
go get

go get不再在模块感知模式下构建或安装软件包。go get现在用来调整go.mod里的依赖。实际上,标志-d会被一直启用。要在当前模块的上下文之外安装一个可执行文件的最新版本,使用go_install_example.com/cmd@latest,可以使用任何版本的查询来代替latest。在Go 1.16添加了这种形式的go install,所以支持旧版本的项目,可能需要提供go installgo 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.modgo.sum文件。(这些文件可以使用go getgo mod tidy,或者go mod download更新。)

go version

go命令现在可以在二进制文件中嵌入版本控制信息。它包括当前签出的修订版,提交时间,以及表明是否存在已编辑或未跟踪的文件的标志。如果go命令是在Git、Mercurial、Fossil或Bazaar仓库中的一个目录中调用的,并且main包和其包含的main模块在同一个仓库中,那么版本控制信息就会被嵌入。这个信息可以通过标志-buildvcs=false省略。

此外,go命令还嵌入了关于构建的信息,包括构建和工具标签(用-tags设置),编译器、汇编器和链接器的标志(如-gcflags),cgo是否被启用,如果被启用,cgo环境变量的值(如CGO_CFLAGS)。VCS和构建信息都可以使用go version -m文件或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标志,它能够与用内存错误检测工具(C编译器选项`-fsanitize=address·)编译的C(或C++)代码进行互操作。

go test

go命令现在支持额外的命令行选项,用于上述新的fuzzing支持。

  • go test支持-fuzz-fuzztime-fuzzminimizetime选项。关于这些的文档,请看go help testflag

  • go clean支持一个-fuzzcache选项。文档见go help testflag

//go:build lines

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.17或更高版本的模块中现已被淘汰的// +build行。

更多信息,见https://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检查器copylockprintfsortslicetestinggoroutinetest都有适度的精度改进,以处理额外的代码模式。这可能会导致现有软件包中出现新的报告错误。例如,printf检查器现在跟踪由串联字符串常量创建的格式化字符串。所以vet会报告一个错误:

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

Runtime

09e635df5b334e21a9b30eb0e982cf22.png

当确定运行频率时,垃圾收集器现在包括垃圾收集器工作的非栈资源(例如,堆栈扫描)。因此,当这些资源明显增多的情况下,垃圾收集器的开销就更可预测。对于大多数应用这些改变基本微乎其微;然而,有一些Go应用程序可能使用少量的内存,而花更多的时间在垃圾回收,或者反过来说,比以前更多。打算采取的解决方法是在必要时调整GOGC

现在,runtime更有效地将内存返回给操作系统,并因此而被调整为更积极地执行。

Go 1.17总体上改进了堆栈跟踪中参数的格式,但对于以寄存器传递的参数,可能会打印出不准确的值。在Go 1.18中,这一点得到了改进,在每个可能不准确的数值后面打印一个问号(?

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


编译器

accd0912542c289fb8855795173ad84f.png

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发布说明。

编译器现在可以内联包含range循环或标记的for循环的函数。

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

因为编译器的类型检查器被全部替换为支持泛型,所以现在一些错误信息可能使用与以前不同的语法。在某些情况下,Go 1.18之前的错误信息提供了更多的细节或以更有帮助的方式表述。我们打算在Go 1.19中解决这些情况。

由于编译器中与支持泛型有关的变化,Go 1.18的编译速度可能比Go 1.17的编译速度大约慢15%。编译后的代码的执行时间不受影响。我们打算在Go 1.19中提高编译器的速度。


链接器

4657570dc5fbe81bd1eed2c859e0d250.png

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

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


Bootstrap

f976b49c132d65badeae3db106ac79b6.png

当从源码构建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或更高版本的bootstrap,这一改变应该能使过渡更加顺利。详情请见go.dev/issue/44505。


核心库

c9f719a349e43bdecceb46e196404216.png

新包debug/buildinfo

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

新包net/netip

新包net/netip定义了新的IP地址类型,Addr。与现有的net.IP类型相比,netip.Addr类型占用更少的内存,是不可改变的,并且具有可比性,所以它支持==,可以作为一个map的key使用。

除了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.ResetWriter.Reset 方法在对nil缓冲区对象调用时,现在使用默认的缓冲区大小。

bytes

新的 Cut函数将分隔符周围的[]byte切成片。它可以取代并简化 Index, IndexByte, IndexRune, 和SplitN.

Trim, TrimLeft, and TrimRight 的许多常见用途,而且现在不需要分配,特别是对于小的ASCII切割集,速度可以提高10倍。

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

crypto/elliptic

P224, P384, 和P521 曲线的实现现在都是由addchain 和fiat-crypto 项目产生的代码支持的,后者是基于正式验证的算术运算模型。他们现在使用更安全的完整公式和内部API。P-224和P-384现在大约快4倍。所有具体的曲线实现现在都是恒定时间的。

在无效的曲线点(那些IsOnCurve方法返回false,并且Unmarshal或对有效点进行操作的Curve方法从未返回的点。)上操作一直是未定义的行为,可能导致密钥恢复攻击,现在新的后端不支持。如果一个无效的点被提供给P224P384P521方法,该方法现在将返回一个随机点。在未来发布的版本中,这种行为可能会改变为确定的panic。

crypto/tls

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

crypto/x509

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

SystemCertPool现在在Windows上可用。

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

CertPool.Subjects已经废弃了。在 Windows、macOS 和 iOS 上,由 SystemCertPool返回的 CertPool 将返回一个池,其中不包括 Subjects 返回的切片中的系统root,因为静态列表不能适当地代表平台策略,而且可能根本无法从平台 APIs 中获得。

对使用依赖MD5和SHA-1哈希值的签名算法 (MD5WithRSA, SHA1WithRSA, 和ECDSAWithSHA1)签署证书的支持可能在Go 1.19中被删除。

debug/dwarf

StructField BasicType 结构现在都有字段DataBitOffset,如果DW_AT_data_bit_offset有值的话,它持有DW_AT_data_bit_offset属性的值。

debug/elf

现已添加常量R_PPC64_RELATIVE

debug/plan9obj

如果文件没有符号部分, File.Symbols方法现在会返回新的输出错误值ErrNoSymbols。

go/ast

根据提案,对go/ast和go/token进行了补充,以支持参数化的函数和类型,以下是对 go/ast 包的补充:

  • FuncTypeTypeSpec 节点有一个新的字段TypeParams来保存类型参数,如果有的话。

  • 新的表达式节点IndexListExpr代表了多个索引的索引表达式,用于实例一个以上显式类型参数的函数和类型。go/constant

新的Kind.String 方法为接收者类型返回一个可读的名称。

go/token

新的常量 TILDE 代表了提案,go/ast和go/token进行了补充,以支持参数化的函数和类型,中的~的标记。

go/types

新的 Config.GoVersion字段集合接收Go语言版本。

根据提案,对go/ast和go/token进行了补充,以支持参数化的函数和类型,以下是对 go/types包的补充:

  • 增加了新的TypeParam类型、工厂函数 NewTypeParam和相关方法来表示一个类型参数。

  • 新类型 TypeParamList 持有一个类型参数的列表。

  • 新类型TypeList持有一个类型的列表。

  • 新的工厂函数 NewSignatureType分配了一个带有(接收器或函数)类型参数的 Signature。为了访问这些类型参数,Signature类型有两个新方法Signature.RecvTypeParamsSignature.TypeParams

  • Named 类型有四个新方法:Named.Origin用于获取实例化类型的原始参数化类型, Named.TypeArgsNamed.TypeParams 用于获取实例化或参数化类型的类型参数, Named.SetTypeParams用于设置类型参数(例如,当导入一个命名的类型时,由于可能的循环,命名类型的分配和类型参数的设置不能同时进行)。

  • 接口类型有四个新方法:Interface.IsComparableInterface.IsMethodSet 用于查询接口定义的类型集的属性, Interface.MarkImplicitInterface.IsImplicit 用于设置和测试接口是否是围绕类型约束的隐式接口。

  • 新的类型 UnionTerm,工厂函数NewUnionNewTerm,以及相关的方法被添加到接口中来表示类型集合。

  • 新函数 Instantiate 实例化了一个参数化的类型。

  • 新的 Info.Instances map通过新的Instance类型记录函数和类型的实例化。

  • 增加了新的ArgumentError类型和相关方法来表示与类型参数有关的错误。

  • 增加了新的类型 Context 和工厂函数 NewContext ,以便通过新的Config.Context 字段,在类型检查的包之间共享相同的类型实例。

AssignableTo, ConvertibleTo, Implements, Identical, IdenticalIgnoreTags, 和AssertableTo 现在也可以处理属于或包含泛型接口的参数,即接口在Go代码中只能作为类型约束所使用。请注意,AssignableTo, ConvertibleTo, ImplementsAssertableTo 的行为在参数为非实例化泛型的情况下是未定义的,如果第一个参数是一个泛型的接口,那么AssertableTo的行为是未定义的。

html/template

在一个range管道内,新的{{break}}命令将提前结束循环,新的{{continue}}命令将立即开始下一个循环迭代。and函数不再对所有参数进行评估;它在第一个参数评估为false后就停止评估参数。同样,or函数现在在第一个参数评估为 true 后就停止评估参数。如果任何一个参数是一个函数调用,这就有区别了。

image/draw

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

net

net.Error.Temporary 已经废弃。

net/http

在WebAssembly目标上,Transport 中的 Dial, DialContext, DialTLSDialTLSContext 方法字段现在将被正确使用,如果要明确的话,就是用于创建HTTP请求。

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

新的 MaxBytesHandler函数创建了一个Handler,用MaxBytesReader包装它的ResponseWriterRequest.Body

当查询包含非ASCII字符的域名时,Unicode到ASCII的转换现在是按照 Unicode IDNA Compatibility Processing标准(UTS #46)中定义的非过渡性处理进行的。改变了四个不同的符文的解释:ß, ς, zero-width joiner U+200D,和zero-width non-joiner U+200C。非过渡性处理与大多数应用程序和网络浏览器一致。

os/user

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

reflect

新的 Value.SetIterKeyValue.SetIterValue 方法使用map迭代器作为源来设置一个Value。它们等同于Value.Set(iter.Key())Value.Set(iter.Value()),但内存分配得更少。

新的Value.UnsafePointer方法将Value的值作为一个unsafe.Pointer返回。这允许调用者从 Value.UnsafeAddrValue.Pointer 迁移,以消除在调用的地方需要执行uintptr到unsafe.Pointer的转换(因为unsafe.Pointer规则要求)。

新的MapIter.Reset方法改变了它的接收器,在一个不同的map上进行迭代。使用MapIter.Reset 可以在多个map上进行无内存分配的迭代。

一些方法( Value.CanInt, Value.CanUint, Value.CanFloat, Value.CanComplex )已经被添加到Value中,以测试转换是否安全。

为了避免在Value.FieldByIndex中通过一个指向嵌入式结构的空指针步进时发生的panic,添加了Value.FieldByIndexErr

reflect.Ptrreflect.PtrTo 已经分别更名为 reflect.Pointerreflect.PointerTo,以便与 reflect 包的其他部分保持一致。旧的名字将继续工作,但在未来的Go版本中会被废弃。

regexp

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

runtime/debug

BuildInfo结构有两个新字段,包含关于二进制文件如何构建的额外信息:GoVersion持有用于构建二进制文件的Go版本。.SettingsBuildSettings结构的一个切片,持有描述构建的键/值对。

runtime/pprof

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

strconv

strconv.Unquote现在拒绝接受Unicode surrogate halves。

strings

新的 Cut函数将分隔符周围的string切成片。它可以取代并简化 Index, IndexByte, IndexRune, 和SplitN.

新的Clone函数复制了输入字符串,返回的克隆字符串没有引用输入字符串的内存。

Trim, TrimLeft, and TrimRight 的许多常见用途,而且现在不需要分配,特别是对于小的ASCII切割集,速度可以提高10倍。

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

sync

新的方法Mutex.TryLock, RWMutex.TryLockRWMutex.TryRLock,将在当前没有锁的情况下获取锁。

syscall

为Windows引入了新的函数 SyscallN,允许以任意数量的参数进行调用。因此, Syscall, Syscall6, Syscall9, Syscall12, Syscall15 Syscall18 将会被弃用,而使用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 类型被上述新的fuzzing支持所使用。Tests现在也支持命令行参数 -test.fuzz, -test.fuzztime, 和-test.fuzzminimizetime

text/template

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

and函数不再对所有参数进行评估;它在第一个参数评估为false后就停止评估参数。同样,or函数现在在第一个参数评估为 true 后就停止评估参数。如果任何一个参数是一个函数调用,这就有区别了。

text/template/parse

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

unicode/utf8

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

原文地址:https://tip.golang.org/doc/go1.18

原文作者:golang.org

本文永久链接:https://github.com/gocn/translator/blob/master/2022/w12_Go_1_18_Release_Notes.md

译者:zxmfke

校对:

820e8b6f771125b6f29b215539c9fd30.png

想要了解更多与 Go 语言相关的内容,添加微信号:gocnio, 让小编拉你入群哦~欢迎入群和我们进行交流~

1682ecfae82cbc064af29ca26b4412c5.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值