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.Add
:unsafe.Add(ptr, len)
将len
添加到ptr
并返回更新后的指针unsafe.Pointer(uintptr(ptr) + uintptr(len))
。 -
unsafe.Slice
:对于类型为*T
的表达式ptr
,unsafe.Slice(ptr, len)
返回一个类型为[]T
的切片,其底层数组从ptr
开始,长度和容量为len
。
添加 unsafe 包的增强功能是为了简化编写符合 unsafe.Pointer
安全规则的代码,但这些规则保持不变。特别是,正确使用 unsafe.Pointer
的现有程序仍然有效,新程序在使用 unsafe.Add
或 unsafe.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/amd64
和 openbsd/arm64
端口)通过 libc
进行系统调用,而不是直接使用机器指令。在 Go 1.17 中,OpenBSD 上的 32 位 x86 和 32 位 ARM 架构(openbsd/386
和 openbsd/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
标志也绕过了模块校验和验证,如果您需要该功能,请使用 GOPRIVATE
或 GONOSUMDB
。有关详细信息,请参阅 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.mod
和 go.sum
文件,否则这可能会干扰 go
命令在 vendor
树中调用时识别正确模块根的能力。
密码提示
go
命令现在默认在通过 SSH 获取 Git 仓库时抑制 SSH 密码提示和 Git 凭据管理器提示,就像它以前对其他 Git 密码提示所做的那样。使用受密码保护的 SSH 向私有 Git 仓库进行身份验证的用户可以配置 ssh-agent
,以使 go
命令能够使用受密码保护的 SSH 密钥。
go mod download
当不带参数调用 go mod download
时,它将不再保存下载模块内容的校验和到 go.sum
。它仍然可能对 go.mod
和 go.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
接口的类型上命名为 As
、Is
或 Unwrap
的方法,这些方法的签名与 errors
包预期的签名不同。errors.{As,Is,Unwrap}
函数期望这些方法分别实现 Is(error) bool
、As(interface{}) bool
或 Unwrap() error
。errors.{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/amd64
、darwin/amd64
和 windows/amd64
端口)上启用。
此更改不影响任何安全 Go 代码的功能,旨在对大多数汇编代码没有影响。它可能会影响在访问函数参数时违反 unsafe.Pointer
规则,或依赖涉及比较函数代码指针的未文档行为的代码。为了保持与现有汇编函数的兼容性,编译器会生成适配器函数,在新基于寄存器的调用约定和以前基于堆栈的调用约定之间进行转换。这些适配器通常对用户是不可见的,但通过 reflect.ValueOf(fn).Pointer()
或 unsafe.Pointer
在汇编代码中获取 Go 函数的地址或在 Go 代码中获取汇编函数的地址现在将返回适配器的地址。依赖这些代码指针值的代码可能不再按预期运行。适配器还可能在两种情况下导致非常小的性能开销:通过 func
值从 Go 间接调用汇编函数,以及从汇编调用 Go 函数。
运行时(当发生未捕获的 panic 或调用 runtime.Stack
时打印)的堆栈跟踪格式得到了改进。以前,函数参数以基于内存布局的十六进制单词打印。现在,源代码中的每个参数都单独打印,用逗号分隔。聚合类型(结构体、数组、字符串、切片、接口和复杂类型)的参数用大括号分隔。需要注意的是,仅存在于寄存器中且未存储到内存中的参数值可能不准确。函数返回值(通常不准确)不再打印。
包含闭包的函数现在可以内联。此更改的一个影响是,包含闭包的函数可能会为函数内联的每个位置生成不同的闭包代码指针。Go 函数值不能直接比较,但此更改可能会揭示使用 reflect
或 unsafe.Pointer
绕过此语言限制并按代码指针比较函数的代码中的错误。
链接器
当链接器使用外部链接模式时(这是链接使用 cgo 的程序的默认模式),并且链接器使用 -I
选项调用时,该选项现在将作为 -Wl,--dynamic-linker
选项传递给外部链接器。
标准库
Cgo
runtime/cgo
包现在提供了一个新功能,允许将任何 Go 值转换为可以安全地在 C 和 Go 之间传递值的安全表示。有关更多信息,请参阅 runtime/cgo.Handle。
URL 查询解析
net/url
和 net/http
包以前除了 "&"
(和号)之外,还接受 ";"
(分号)作为 URL 查询中的设置分隔符。现在,带有未进行百分比编码的分号的设置将被拒绝,并且 net/http
服务器在请求 URL 中遇到此类设置时,会向 Server.ErrorLog
记录警告。
例如,在 Go 1.17 之前,URL example?a=1;b=2&c=3
的 Query
方法会返回 map[a:[1] b:[2] c:[3]]
,而现在它返回 map[c:[3]]
。
当遇到这样的查询字符串时,URL.Query
和 Request.FormValue
会忽略任何包含分号的设置,ParseQuery
返回剩余的设置和一个错误,而 Request.ParseForm
和 Request.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.OpenRaw
、Writer.CreateRaw
、Writer.Copy
为性能是主要考虑因素的情况提供了支持。
bufio
Writer.WriteRune
方法现在为负的 rune 值写入替换字符 U+FFFD,就像它对其他无效 rune 值所做的那样。
bytes
Buffer.WriteRune
方法现在为负的 rune 值写入替换字符 U+FFFD,就像它对其他无效 rune 值所做的那样。
compress/lzw
NewReader
函数保证返回新类型 Reader
的值,同样 NewWriter
保证返回新类型 Writer
的值。这两个新类型都实现了 Reset
方法(Reader.Reset
、Writer.Reset
),允许重用 Reader
或 Writer
。
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.Context
和 CertificateRequestInfo.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
接口。
新的 NullInt16
和 NullByte
结构体表示可能为 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
Source
和 Node
函数现在将 //go:build
行与 // +build
行同步。如果文件只有 // +build
行,它们将被移动到文件中的适当位置,并添加匹配的 //go:build
行。否则,// +build
行将根据任何现有的 //go:build
行进行覆盖。有关更多信息,请参阅 https://golang.ac.cn/design/draft-gobuild。
go/parser
新的 SkipObjectResolution
Mode
值指示解析器不将标识符解析为其声明。这可能会提高解析速度。
图像
具体的图像类型(RGBA
、Gray16
等)现在实现了一个新的 RGBA64Image
接口。以前实现 draw.Image
的具体类型现在也实现了 image/draw
包中的新接口 draw.RGBA64Image
。
io/fs
新的 FileInfoToDirEntry
函数将 FileInfo
转换为 DirEntry
。
math
math 包现在定义了三个额外的常量:MaxUint
、MaxInt
和 MinInt
。对于 32 位系统,它们的值分别为 2^32 - 1
、2^31 - 1
和 -2^31
。对于 64 位系统,它们的值分别为 2^64 - 1
、2^63 - 1
和 -2^63
。
mime
在 Unix 系统上,MIME 类型表现在会在可用时从本地系统的 共享 MIME-info 数据库中读取。
mime/multipart
Part.FileName
现在将 filepath.Base
应用于返回值。这减轻了接受多部分消息的应用程序中潜在的路径遍历漏洞,例如调用 Request.FormFile
的 net/http
服务器。
net
新的方法 IP.IsPrivate
报告一个地址是否是符合 RFC 1918 的私有 IPv4 地址,或者是否是符合 RFC 4193 的本地 IPv6 地址。
Go DNS 解析器现在在解析仅支持 IPv4 或仅支持 IPv6 的网络的地址时只发送一个 DNS 查询,而不是同时查询两种地址族。
ErrClosed
哨兵错误和 ParseError
错误类型现在实现了 net.Error
接口。
ParseIP
和 ParseCIDR
函数现在会拒绝包含带有前导零的十进制组件的 IPv4 地址。这些组件始终被解释为十进制,但某些操作系统将它们视为八进制。这种不匹配理论上可能导致安全问题,如果 Go 应用程序用于验证 IP 地址,然后将这些 IP 地址以其原始形式与将组件解释为八进制的非 Go 应用程序一起使用。通常建议在验证后始终重新编码值,这可以避免此类解析器不一致问题。
net/http
在客户端或服务器执行 TLS 握手时,net/http
包现在使用新的 (*tls.Conn).HandshakeContext
和 Request
上下文。
将 Server
的 ReadTimeout
或 WriteTimeout
字段设置为负值现在表示没有超时,而不是立即超时。
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.IsExported
和 Method.IsExported
方法报告结构体字段或类型方法是否已导出。它们提供了检查 PkgPath
是否为空的更易读的替代方案。
新的 VisibleFields
函数返回结构体类型中所有可见字段,包括匿名结构体成员中的字段。
ArrayOf
函数在调用时带有负长度参数时现在会发生 panic。
检查 Type.ConvertibleTo
方法已不足以保证调用 Value.Convert
不会发生 panic。当将 `[]T` 转换为 `*[N]T` 时,如果切片的长度小于 N,它可能会发生 panic。请参阅上面的语言更改部分。
Value.Convert
和 Type.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
现在具有 Swap
和 CompareAndSwap
方法,这些方法提供了额外的原子操作。
syscall
GetQueuedCompletionStatus
和 PostQueuedCompletionStatus
函数现在已弃用。这些函数签名不正确,并被 golang.org/x/sys/windows
包中的等效函数取代。
在类 Unix 系统上,子进程的进程组现在在信号被阻塞的情况下设置。这可以避免当父进程在后台进程组中时向子进程发送 SIGTTOU
。
SysProcAttr
的 Windows 版本有两个新字段。AdditionalInheritedHandles
是一个额外的句柄列表,将由新的子进程继承。ParentProcess
允许指定新进程的父进程。
常量 MSG_CMSG_CLOEXEC
现在在 DragonFly 和所有 OpenBSD 系统上定义(它已经定义在某些 OpenBSD 系统和所有 FreeBSD、NetBSD 和 Linux 系统上)。
常量 SYS_WAIT6
和 WEXITED
现在在 NetBSD 系统上定义(SYS_WAIT6
已经定义在 DragonFly 和 FreeBSD 系统上;WEXITED
已经定义在 Darwin、DragonFly、FreeBSD、Linux 和 Solaris 系统上)。
testing
添加了一个新的 测试标志 -shuffle
,用于控制测试和基准测试的执行顺序。
新的 T.Setenv
和 B.Setenv
方法支持在测试或基准测试期间设置环境变量。
text/template/parse
新的 SkipFuncCheck
Mode
值更改模板解析器,使其不再验证函数是否已定义。
time
Time
类型现在有一个 GoString
方法,当在 fmt
包中使用 %#v
格式说明符打印时,它将返回一个更有用的时间值。
新的 Time.IsDST
方法可用于检查时间在其配置位置是否为夏令时。
新的 Time.UnixMilli
和 Time.UnixMicro
方法分别返回自 1970 年 1 月 1 日 UTC 以来经过的毫秒数和微秒数。
新的 UnixMilli
和 UnixMicro
函数返回与给定 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
Is
、IsGraphic
、IsLetter
、IsLower
、IsMark
、IsNumber
、IsPrint
、IsPunct
、IsSpace
、IsSymbol
和 IsUpper
函数现在对负的 rune 值返回 false
,就像它们对其他无效的 rune 值所做的那样。