Go 1.17 发布说明

Go 1.17 简介

最新的 Go 版本,1.17,在 Go 1.16 发布六个月后到来。其大部分更改都在工具链、运行时和库的实现中。一如既往,该版本保持了 Go 1 兼容性承诺。我们预计几乎所有 Go 程序都将继续像以前一样编译和运行。

语言变化

Go 1.17 包含对语言的三个小改进。

  • 从切片到数组指针的转换:类型为 []T 的表达式 s 现在可以转换为数组指针类型 *[N]T。如果 a 是此类转换的结果,那么在范围内的相应索引将引用相同的底层元素:&a[i] == &s[i] 对于 0 <= i < N。如果 len(s) 小于 N,则转换会发生 panic。
  • unsafe.Addunsafe.Add(ptr, len)len 添加到 ptr 并返回更新后的指针 unsafe.Pointer(uintptr(ptr) + uintptr(len))
  • unsafe.Slice:对于类型为 *T 的表达式 ptrunsafe.Slice(ptr, len) 返回一个类型为 []T 的切片,其底层数组从 ptr 开始,长度和容量为 len

添加 unsafe 包的增强功能是为了简化编写符合 unsafe.Pointer 安全规则的代码,但这些规则保持不变。特别是,正确使用 unsafe.Pointer 的现有程序仍然有效,新程序在使用 unsafe.Addunsafe.Slice 时仍必须遵循这些规则。

请注意,新的切片到数组指针的转换是类型转换在运行时可能发生 panic 的第一个案例。假设类型转换永远不会发生 panic 的分析工具应更新以考虑这种可能性。

移植

Darwin

如 Go 1.16 发布说明中宣布,Go 1.17 需要 macOS 10.13 High Sierra 或更高版本;对先前版本的支持已停止。

Windows

Go 1.17 增加了对 Windows 上的 64 位 ARM 架构(windows/arm64 端口)的支持。此端口支持 cgo。

OpenBSD

OpenBSD 上的 64 位 MIPS 架构(openbsd/mips64 端口)现在支持 cgo。

在 Go 1.16 中,OpenBSD 上的 64 位 x86 和 64 位 ARM 架构(openbsd/amd64openbsd/arm64 端口)通过 libc 进行系统调用,而不是直接使用机器指令。在 Go 1.17 中,OpenBSD 上的 32 位 x86 和 32 位 ARM 架构(openbsd/386openbsd/arm 端口)也采用了这种方式。这确保了与 OpenBSD 6.9 及更高版本的兼容性,OpenBSD 6.9 及更高版本要求非静态 Go 二进制文件通过 libc 进行系统调用。

ARM64

Go 程序现在在所有操作系统的 64 位 ARM 架构上维护堆栈帧指针。以前,堆栈帧指针只在 Linux、macOS 和 iOS 上启用。

loong64 GOARCH 值已保留

主 Go 编译器尚未支持 LoongArch 架构,但我们已保留 GOARCH 值“loong64”。这意味着 Go 工具现在将忽略名为 *_loong64.go 的 Go 文件,除非正在使用该 GOARCH 值。

工具

Go 命令

go 1.17 模块中修剪过的模块图

如果模块指定 go 1.17 或更高版本,则模块图只包含其他 go 1.17 模块的*直接*依赖项,而不是其完整的传递依赖项。(有关详细信息,请参阅模块图修剪。)

为了让 go 命令使用修剪后的模块图正确解析传递导入,每个模块的 go.mod 文件需要包含有关与该模块相关的传递依赖项的更多详细信息。如果模块在其 go.mod 文件中指定 go 1.17 或更高版本,则其 go.mod 文件现在包含为每个提供传递导入包的模块显式require 指令。(在以前的版本中,go.mod 文件通常只包含*直接*导入包的显式要求。)

由于模块图修剪所需的扩展 go.mod 文件包含加载主模块中任何包的导入所需的所有依赖项,如果主模块指定 go 1.17 或更高版本,则 go 工具不再读取(甚至下载)依赖项的 go.mod 文件,如果它们不是完成请求命令所必需的。(请参阅延迟加载。)

由于扩展的 Go 1.17 go.mod 文件中显式要求的数量可能大大增加,因此在 go 1.17 模块中新添加的对*间接*依赖项的要求将与包含直接依赖项的块分开维护在一个单独的 require 块中。

为方便升级到 Go 1.17 修剪后的模块图,go mod tidy 子命令现在支持 -go 标志,用于设置或更改 go.mod 文件中的 go 版本。要将现有模块的 go.mod 文件转换为 Go 1.17,而不更改其依赖项的选定版本,请运行

  go mod tidy -go=1.17

默认情况下,go mod tidy 会验证与主模块相关的依赖项的选定版本是否与先前 Go 版本(对于指定 go 1.17 的模块,为 Go 1.16)使用的版本相同,并保留该版本所需的 go.sum 条目,即使是对于其他命令通常不需要的依赖项。

-compat 标志允许覆盖该版本以支持旧版本(或只支持新版本),直至 go.mod 文件中 go 指令指定的版本。要仅为 Go 1.17 整理 go 1.17 模块,而不保存 Go 1.16 的校验和(或检查与 Go 1.16 的一致性)

  go mod tidy -compat=1.17

请注意,即使主模块已通过 -compat=1.17 进行了整理,从 go 1.16 或更早版本模块中 require 该模块的用户仍然可以使用它,前提是这些包仅使用兼容的语言和库功能。

go mod graph 子命令也支持 -go 标志,这使得它报告由指定 Go 版本看到的图,显示可能被修剪掉的依赖项。

模块弃用评论

模块作者可以通过向 go.mod 添加 // Deprecated: 注释,然后标记新版本来弃用模块。如果命令行中指定的包所需的模块已弃用,go get 现在会打印警告。go list -m -u 打印所有依赖项的弃用信息(使用 -f-json 显示完整消息)。go 命令将不同的主版本视为不同的模块,因此此机制可用于例如向用户提供新主版本的迁移说明。

go get

go get -insecure 标志已弃用并已删除。要允许在获取依赖项时使用不安全的方案,请使用 GOINSECURE 环境变量。-insecure 标志也绕过了模块校验和验证,如果您需要该功能,请使用 GOPRIVATEGONOSUMDB。有关详细信息,请参阅 go help environment

在主模块之外安装命令(不带 -d 标志)时,go get 会打印弃用警告。应改用 go install cmd@version 来安装特定版本的命令,使用 @latest@v1.2.3 等后缀。在 Go 1.18 中,-d 标志将始终启用,go get 将仅用于更改 go.mod 中的依赖项。

go.mod 文件缺少 go 指令

如果主模块的 go.mod 文件不包含 go 指令,并且 go 命令无法更新 go.mod 文件,则 go 命令现在假定为 go 1.11 而不是当前版本。(go mod init 自 Go 1.12 以来已自动添加 go 指令。)

如果模块依赖项缺少显式的 go.mod 文件,或者其 go.mod 文件不包含 go 指令,则 go 命令现在假定该依赖项为 go 1.16 而不是当前版本。(在 GOPATH 模式下开发的依赖项可能缺少 go.mod 文件,并且 vendor/modules.txt 迄今为止从未记录依赖项 go.mod 文件指示的 go 版本。)

vendor 内容

如果主模块指定 go 1.17 或更高版本,go mod vendor 现在会使用每个 vendored 模块在其自己的 go.mod 文件中指示的 go 版本来注释 vendor/modules.txt。从 vendored 源代码构建模块的包时,将使用注释的版本。

如果主模块指定 go 1.17 或更高版本,go mod vendor 现在会省略 vendored 依赖项的 go.modgo.sum 文件,否则这可能会干扰 go 命令在 vendor 树中调用时识别正确模块根的能力。

密码提示

go 命令现在默认在通过 SSH 获取 Git 仓库时抑制 SSH 密码提示和 Git 凭据管理器提示,就像它以前对其他 Git 密码提示所做的那样。使用受密码保护的 SSH 向私有 Git 仓库进行身份验证的用户可以配置 ssh-agent,以使 go 命令能够使用受密码保护的 SSH 密钥。

go mod download

当不带参数调用 go mod download 时,它将不再保存下载模块内容的校验和到 go.sum。它仍然可能对 go.modgo.sum 进行必要的更改以加载构建列表。这与 Go 1.15 中的行为相同。要保存所有模块的校验和,请使用 go mod download all

//go:build

go 命令现在理解 //go:build 行并优先于 // +build 行。新语法使用布尔表达式,就像 Go 一样,应该更不容易出错。截至此版本,新语法已完全支持,所有 Go 文件都应更新为具有相同含义的两种形式。为了帮助迁移,gofmt 现在会自动同步这两种形式。有关语法和迁移计划的更多详细信息,请参阅 https://golang.ac.cn/design/draft-gobuild

go run

go run 现在接受带有版本后缀的参数(例如,go run example.com/cmd@v1.0.0)。这使得 go run 在模块感知模式下构建和运行包,忽略当前目录或任何父目录中的 go.mod 文件(如果存在)。这对于运行可执行文件而无需安装它们或无需更改当前模块的依赖项很有用。

Gofmt

gofmt (和 go fmt) 现在将 //go:build 行与 // +build 行同步。如果文件只有 // +build 行,它们将被移动到文件中的适当位置,并添加匹配的 //go:build 行。否则,// +build 行将根据任何现有的 //go:build 行进行覆盖。有关更多信息,请参阅 https://golang.ac.cn/design/draft-gobuild

Vet

//go:build// +build 行不匹配的新警告

vet 工具现在验证 //go:build// +build 行是否在文件的正确部分并相互同步。如果不是,可以使用gofmt来修复它们。有关更多信息,请参阅 https://golang.ac.cn/design/draft-gobuild

对非缓冲通道调用 signal.Notify 的新警告

vet 工具现在会警告对 signal.Notify 的调用,其中传入信号被发送到非缓冲通道。使用非缓冲通道存在丢失信号的风险,因为 signal.Notify 在发送到通道时不会阻塞。例如

c := make(chan os.Signal)
// signals are sent on c before the channel is read from.
// This signal may be dropped as c is unbuffered.
signal.Notify(c, os.Interrupt)

signal.Notify 的用户应使用具有足够缓冲空间的通道,以跟上预期的信号速率。

Is、As 和 Unwrap 方法的新警告

vet 工具现在会警告实现 error 接口的类型上命名为 AsIsUnwrap 的方法,这些方法的签名与 errors 包预期的签名不同。errors.{As,Is,Unwrap} 函数期望这些方法分别实现 Is(error) boolAs(interface{}) boolUnwrap() errorerrors.{As,Is,Unwrap} 函数将忽略同名但签名不同的方法。例如

type MyError struct { hint string }
func (m MyError) Error() string { ... } // MyError implements error.
func (MyError) Is(target interface{}) bool { ... } // target is interface{} instead of error.
func Foo() bool {
    x, y := MyError{"A"}, MyError{"B"}
    return errors.Is(x, y) // returns false as x != y and MyError does not have an `Is(error) bool` function.
}

覆盖率

cover 工具现在使用 golang.org/x/tools/cover 中的优化解析器,在解析大型覆盖率配置文件时可能会明显更快。

编译器

Go 1.17 实现了一种新的函数参数和结果传递方式,使用寄存器而不是堆栈。针对一组代表性的 Go 包和程序的基准测试显示,性能提高了约 5%,二进制文件大小通常减少约 2%。目前,这已在 64 位 x86 架构上的 Linux、macOS 和 Windows(linux/amd64darwin/amd64windows/amd64 端口)上启用。

此更改不影响任何安全 Go 代码的功能,旨在对大多数汇编代码没有影响。它可能会影响在访问函数参数时违反 unsafe.Pointer 规则,或依赖涉及比较函数代码指针的未文档行为的代码。为了保持与现有汇编函数的兼容性,编译器会生成适配器函数,在新基于寄存器的调用约定和以前基于堆栈的调用约定之间进行转换。这些适配器通常对用户是不可见的,但通过 reflect.ValueOf(fn).Pointer()unsafe.Pointer 在汇编代码中获取 Go 函数的地址或在 Go 代码中获取汇编函数的地址现在将返回适配器的地址。依赖这些代码指针值的代码可能不再按预期运行。适配器还可能在两种情况下导致非常小的性能开销:通过 func 值从 Go 间接调用汇编函数,以及从汇编调用 Go 函数。

运行时(当发生未捕获的 panic 或调用 runtime.Stack 时打印)的堆栈跟踪格式得到了改进。以前,函数参数以基于内存布局的十六进制单词打印。现在,源代码中的每个参数都单独打印,用逗号分隔。聚合类型(结构体、数组、字符串、切片、接口和复杂类型)的参数用大括号分隔。需要注意的是,仅存在于寄存器中且未存储到内存中的参数值可能不准确。函数返回值(通常不准确)不再打印。

包含闭包的函数现在可以内联。此更改的一个影响是,包含闭包的函数可能会为函数内联的每个位置生成不同的闭包代码指针。Go 函数值不能直接比较,但此更改可能会揭示使用 reflectunsafe.Pointer 绕过此语言限制并按代码指针比较函数的代码中的错误。

当链接器使用外部链接模式时(这是链接使用 cgo 的程序的默认模式),并且链接器使用 -I 选项调用时,该选项现在将作为 -Wl,--dynamic-linker 选项传递给外部链接器。

标准库

Cgo

runtime/cgo 包现在提供了一个新功能,允许将任何 Go 值转换为可以安全地在 C 和 Go 之间传递值的安全表示。有关更多信息,请参阅 runtime/cgo.Handle

URL 查询解析

net/urlnet/http 包以前除了 "&"(和号)之外,还接受 ";"(分号)作为 URL 查询中的设置分隔符。现在,带有未进行百分比编码的分号的设置将被拒绝,并且 net/http 服务器在请求 URL 中遇到此类设置时,会向 Server.ErrorLog 记录警告。

例如,在 Go 1.17 之前,URL example?a=1;b=2&c=3Query 方法会返回 map[a:[1] b:[2] c:[3]],而现在它返回 map[c:[3]]

当遇到这样的查询字符串时,URL.QueryRequest.FormValue 会忽略任何包含分号的设置,ParseQuery 返回剩余的设置和一个错误,而 Request.ParseFormRequest.ParseMultipartForm 返回一个错误,但仍会根据剩余的设置设置 Request 字段。

net/http 用户可以通过使用新的 AllowQuerySemicolons 处理程序包装器来恢复原始行为。这也会抑制 ErrorLog 警告。请注意,如果不同的系统对缓存键的解释不同,接受分号作为查询分隔符可能会导致安全问题。有关更多信息,请参阅 问题 25192

TLS 严格 ALPN

当设置 Config.NextProtos 时,服务器现在强制执行配置的协议与客户端公布的 ALPN 协议(如果有)之间存在重叠。如果没有相互支持的协议,则连接将以 no_application_protocol 警报关闭,正如 RFC 7301 所要求的那样。这有助于缓解 ALPACA 跨协议攻击

作为例外,当服务器的 Config.NextProtos 中包含值 "h2" 时,HTTP/1.1 客户端将被允许连接,就像它们不支持 ALPN 一样。有关更多信息,请参阅 问题 46310

对库的微小更改

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

archive/zip

新的方法 File.OpenRawWriter.CreateRawWriter.Copy 为性能是主要考虑因素的情况提供了支持。

bufio

Writer.WriteRune 方法现在为负的 rune 值写入替换字符 U+FFFD,就像它对其他无效 rune 值所做的那样。

bytes

Buffer.WriteRune 方法现在为负的 rune 值写入替换字符 U+FFFD,就像它对其他无效 rune 值所做的那样。

compress/lzw

NewReader 函数保证返回新类型 Reader 的值,同样 NewWriter 保证返回新类型 Writer 的值。这两个新类型都实现了 Reset 方法(Reader.ResetWriter.Reset),允许重用 ReaderWriter

crypto/ed25519

crypto/ed25519 包已重写,现在在 amd64 和 arm64 上所有操作的速度大约快了一倍。可观察到的行为没有其他改变。

crypto/elliptic

CurveParams 方法现在会在可用时自动为已知曲线(P-224、P-256 和 P-521)调用更快、更安全的专用实现。请注意,这是一种尽力而为的方法,应用程序应避免使用通用的、非恒定时间的 CurveParams 方法,而应使用专用的 Curve 实现,例如 P256

P521 曲线实现已使用 fiat-crypto 项目生成的代码进行了重写,该项目基于形式化验证的算术运算模型。它现在是常数时间,在 amd64 和 arm64 上的速度快了三倍。可观察到的行为没有其他改变。

crypto/rand

crypto/rand 包现在在 macOS 上使用 getentropy 系统调用,在 Solaris、Illumos 和 DragonFlyBSD 上使用 getrandom 系统调用。

crypto/tls

新的 Conn.HandshakeContext 方法允许用户控制正在进行的 TLS 握手的取消。通过新的 ClientHelloInfo.ContextCertificateRequestInfo.Context 方法,可以在各种回调中访问提供的上下文。握手完成后取消上下文没有效果。

密码套件排序现在完全由 crypto/tls 包处理。目前,密码套件根据其安全性、性能和硬件支持进行排序,同时考虑本地和对等方的硬件。Config.CipherSuites 字段的顺序现在被忽略,Config.PreferServerCipherSuites 字段也是如此。请注意,Config.CipherSuites 仍然允许应用程序选择要启用的 TLS 1.0-1.2 密码套件。

3DES 密码套件已移至 InsecureCipherSuites,原因是存在基本的块大小相关弱点。由于上述密码套件排序的改变,它们仍然默认启用,但仅作为最后手段。

从下个版本 Go 1.18 开始,crypto/tls 客户端的 Config.MinVersion 将默认为 TLS 1.2,默认禁用 TLS 1.0 和 TLS 1.1。应用程序可以通过显式设置 Config.MinVersion 来覆盖此更改。这不会影响 crypto/tls 服务器。

crypto/x509

CreateCertificate 现在会在提供的私钥与父级公钥(如果有)不匹配时返回错误。生成的证书将无法验证。

临时 GODEBUG=x509ignoreCN=0 标志已移除。

ParseCertificate 已重写,现在消耗的资源减少约 70%。处理 WebPKI 证书时的可观察行为没有其他改变,除了错误消息。

在 BSD 系统上,现在会搜索 /etc/ssl/certs 以查找受信任的根。这增加了对 FreeBSD 12.2+ 中新系统受信任证书存储的支持。

从下个版本 Go 1.18 开始,crypto/x509 将拒绝使用 SHA-1 哈希函数签名的证书。这不适用于自签名根证书。SHA-1 的实际攻击已在 2017 年得到证实,并且自 2015 年以来,公共信任的证书颁发机构就没有再颁发 SHA-1 证书。

database/sql

DB.Close 方法现在会关闭 connector 字段,如果此字段中的类型实现了 io.Closer 接口。

新的 NullInt16NullByte 结构体表示可能为 null 的 int16 和 byte 值。它们可以作为 Scan 方法的目标,类似于 NullString。

debug/elf

已添加 SHT_MIPS_ABIFLAGS 常量。

encoding/binary

binary.Uvarint 将在 10 bytes 后停止读取以避免浪费计算。如果需要超过 10 bytes,则返回的字节数为 -11
以前的 Go 版本在读取不正确编码的 varint 时可能会返回更大的负数。

encoding/csv

新的 Reader.FieldPos 方法返回与 Read 最近返回的记录中给定字段的开头对应的行和列。

encoding/xml

当注释出现在 Directive 中时,它现在被替换为单个空格,而不是完全省略。

带有前导、尾随或多个冒号的无效元素或属性名称现在将未修改地存储到 Name.Local 字段中。

flag

如果指定了无效名称,标志声明现在会发生 panic。

go/build

新的 Context.ToolTags 字段保存与当前 Go 工具链配置相适应的构建标签。

go/format

SourceNode 函数现在将 //go:build 行与 // +build 行同步。如果文件只有 // +build 行,它们将被移动到文件中的适当位置,并添加匹配的 //go:build 行。否则,// +build 行将根据任何现有的 //go:build 行进行覆盖。有关更多信息,请参阅 https://golang.ac.cn/design/draft-gobuild

go/parser

新的 SkipObjectResolution Mode 值指示解析器不将标识符解析为其声明。这可能会提高解析速度。

图像

具体的图像类型(RGBAGray16 等)现在实现了一个新的 RGBA64Image 接口。以前实现 draw.Image 的具体类型现在也实现了 image/draw 包中的新接口 draw.RGBA64Image

io/fs

新的 FileInfoToDirEntry 函数将 FileInfo 转换为 DirEntry

math

math 包现在定义了三个额外的常量:MaxUintMaxIntMinInt。对于 32 位系统,它们的值分别为 2^32 - 12^31 - 1-2^31。对于 64 位系统,它们的值分别为 2^64 - 12^63 - 1-2^63

mime

在 Unix 系统上,MIME 类型表现在会在可用时从本地系统的 共享 MIME-info 数据库中读取。

mime/multipart

Part.FileName 现在将 filepath.Base 应用于返回值。这减轻了接受多部分消息的应用程序中潜在的路径遍历漏洞,例如调用 Request.FormFilenet/http 服务器。

net

新的方法 IP.IsPrivate 报告一个地址是否是符合 RFC 1918 的私有 IPv4 地址,或者是否是符合 RFC 4193 的本地 IPv6 地址。

Go DNS 解析器现在在解析仅支持 IPv4 或仅支持 IPv6 的网络的地址时只发送一个 DNS 查询,而不是同时查询两种地址族。

ErrClosed 哨兵错误和 ParseError 错误类型现在实现了 net.Error 接口。

ParseIPParseCIDR 函数现在会拒绝包含带有前导零的十进制组件的 IPv4 地址。这些组件始终被解释为十进制,但某些操作系统将它们视为八进制。这种不匹配理论上可能导致安全问题,如果 Go 应用程序用于验证 IP 地址,然后将这些 IP 地址以其原始形式与将组件解释为八进制的非 Go 应用程序一起使用。通常建议在验证后始终重新编码值,这可以避免此类解析器不一致问题。

net/http

在客户端或服务器执行 TLS 握手时,net/http 包现在使用新的 (*tls.Conn).HandshakeContextRequest 上下文。

ServerReadTimeoutWriteTimeout 字段设置为负值现在表示没有超时,而不是立即超时。

ReadRequest 函数现在在请求有多个 Host 头部时返回错误。

当重定向到 URL 的清除版本时,ServeMux 现在总是在 Location 头部中使用相对 URL。以前它会回显请求的完整 URL,如果客户端可以被诱导发送绝对请求 URL,这可能导致意外重定向。

在解释 net/http 处理的某些 HTTP 头部时,非 ASCII 字符现在将被忽略或拒绝。

如果 Request.ParseForm 在被 Request.ParseMultipartForm 调用时返回错误,后者现在在返回之前会继续填充 Request.MultipartForm

net/http/httptest

ResponseRecorder.WriteHeader 现在会在提供的代码不是有效的三位数 HTTP 状态码时发生 panic。这与 net/http 包中的 ResponseWriter 实现的行为一致。

net/url

新的方法 Values.Has 报告是否设置了查询参数。

os

File.WriteString 方法已优化,不再复制输入字符串。

reflect

新的 Value.CanConvert 方法报告值是否可以转换为某种类型。这可以用于避免在切片太短时将切片转换为数组指针类型时发生 panic。以前,为此使用 Type.ConvertibleTo 就足够了,但新允许的从切片到数组指针类型的转换即使类型可转换也可能发生 panic。

新的 StructField.IsExportedMethod.IsExported 方法报告结构体字段或类型方法是否已导出。它们提供了检查 PkgPath 是否为空的更易读的替代方案。

新的 VisibleFields 函数返回结构体类型中所有可见字段,包括匿名结构体成员中的字段。

ArrayOf 函数在调用时带有负长度参数时现在会发生 panic。

检查 Type.ConvertibleTo 方法已不足以保证调用 Value.Convert 不会发生 panic。当将 `[]T` 转换为 `*[N]T` 时,如果切片的长度小于 N,它可能会发生 panic。请参阅上面的语言更改部分。

Value.ConvertType.ConvertibleTo 方法已修复,不再将不同包中同名类型视为相同,以匹配语言允许的行为。

runtime/metrics

添加了新的度量指标,用于跟踪已分配和已释放的总字节数和对象数。还添加了一个新的度量指标,用于跟踪 goroutine 调度延迟的分布。

runtime/pprof

块剖析不再偏向于不常见的长事件而牺牲常见的短事件。

strconv

strconv 包现在使用 Ulf Adams 的 Ryū 算法来格式化浮点数。该算法在大多数输入上提高了性能,在最坏情况输入上速度提高了 99% 以上。

新的 QuotedPrefix 函数返回输入开头带引号的字符串(由 Unquote 理解)。

strings

Builder.WriteRune 方法现在为负的 rune 值写入替换字符 U+FFFD,就像它对其他无效 rune 值所做的那样。

sync/atomic

atomic.Value 现在具有 SwapCompareAndSwap 方法,这些方法提供了额外的原子操作。

syscall

GetQueuedCompletionStatusPostQueuedCompletionStatus 函数现在已弃用。这些函数签名不正确,并被 golang.org/x/sys/windows 包中的等效函数取代。

在类 Unix 系统上,子进程的进程组现在在信号被阻塞的情况下设置。这可以避免当父进程在后台进程组中时向子进程发送 SIGTTOU

SysProcAttr 的 Windows 版本有两个新字段。AdditionalInheritedHandles 是一个额外的句柄列表,将由新的子进程继承。ParentProcess 允许指定新进程的父进程。

常量 MSG_CMSG_CLOEXEC 现在在 DragonFly 和所有 OpenBSD 系统上定义(它已经定义在某些 OpenBSD 系统和所有 FreeBSD、NetBSD 和 Linux 系统上)。

常量 SYS_WAIT6WEXITED 现在在 NetBSD 系统上定义(SYS_WAIT6 已经定义在 DragonFly 和 FreeBSD 系统上;WEXITED 已经定义在 Darwin、DragonFly、FreeBSD、Linux 和 Solaris 系统上)。

testing

添加了一个新的 测试标志 -shuffle,用于控制测试和基准测试的执行顺序。

新的 T.SetenvB.Setenv 方法支持在测试或基准测试期间设置环境变量。

text/template/parse

新的 SkipFuncCheck Mode 值更改模板解析器,使其不再验证函数是否已定义。

time

Time 类型现在有一个 GoString 方法,当在 fmt 包中使用 %#v 格式说明符打印时,它将返回一个更有用的时间值。

新的 Time.IsDST 方法可用于检查时间在其配置位置是否为夏令时。

新的 Time.UnixMilliTime.UnixMicro 方法分别返回自 1970 年 1 月 1 日 UTC 以来经过的毫秒数和微秒数。
新的 UnixMilliUnixMicro 函数返回与给定 Unix 时间对应的本地 Time

该包现在接受逗号“,”作为解析和格式化时间时小数秒的分隔符。例如,现在接受以下时间布局

  • 2006-01-02 15:04:05,999999999 -0700 MST
  • Mon Jan _2 15:04:05,000000 2006
  • Monday, January 2 15:04:05,000 2006

新的常量 Layout 定义了参考时间。

unicode

IsIsGraphicIsLetterIsLowerIsMarkIsNumberIsPrintIsPunctIsSpaceIsSymbolIsUpper 函数现在对负的 rune 值返回 false,就像它们对其他无效的 rune 值所做的那样。