Go 1.10 版本说明

Go 1.10 简介

最新的 Go 版本 1.10,是在 Go 1.9 发布六个月后发布的。其大部分变更都集中在工具链、运行时和库的实现上。与以往一样,此版本保持了 Go 1 的 兼容性承诺。我们预计几乎所有 Go 程序都将像以前一样继续编译和运行。

此版本改进了 已构建包的缓存,添加了 成功测试结果的缓存,在测试期间自动运行 vet,并允许 通过 cgo 直接在 Go 和 C 之间传递字符串值。新的 硬编码安全编译器选项集 可能会导致在使用旧版本成功构建的代码中出现意外的 invalid flag 错误。

语言变更

语言规范没有重大变更。

一个涉及无类型常量移位的极端情况已得到澄清,因此编译器已更新以允许索引表达式 x[1.0 << s],其中 s 是一个无符号整数;go/types 包之前已经支持了这种操作。

方法表达式的语法已更新,以放宽语法,允许任何类型表达式作为接收者;这与编译器已实现的内容相匹配。例如,struct{io.Reader}.Read 是一种有效的(尽管不常见)方法表达式,编译器之前已经接受了这种表达式,现在语言语法也允许它。

移植

此版本中没有新的受支持操作系统或处理器架构。大部分工作都集中在加强对现有移植的支持上,特别是 汇编器中的新指令 以及对编译器生成的代码的改进。

正如 在 Go 1.9 版本说明中宣布的那样,Go 1.10 现在需要 FreeBSD 10.3 或更高版本;对 FreeBSD 9.3 的支持已被移除。

Go 现在再次在 NetBSD 上运行,但需要尚未发布的 NetBSD 8。只有 GOARCH amd64386 已得到修复。arm 移植仍然无法使用。

在 32 位 MIPS 系统上,新的环境变量设置 GOMIPS=hardfloat(默认值)和 GOMIPS=softfloat 用于选择是使用硬件指令还是软件仿真来执行浮点计算。

Go 1.10 是最后一个可以在 OpenBSD 6.0 上运行的版本。Go 1.11 将需要 OpenBSD 6.2。

Go 1.10 是最后一个可以在 OS X 10.8 Mountain Lion 或 OS X 10.9 Mavericks 上运行的版本。Go 1.11 将需要 OS X 10.10 Yosemite 或更高版本。

Go 1.10 是最后一个可以在 Windows XP 或 Windows Vista 上运行的版本。Go 1.11 将需要 Windows 7 或更高版本。

工具

默认 GOROOT & GOTMPDIR

如果环境变量 $GOROOT 未设置,go 工具之前使用工具链编译期间设置的默认 GOROOT。现在,在回退到该默认值之前,go 工具会尝试从其自己的可执行文件路径推断 GOROOT。这使得二进制分发包可以解压缩到文件系统中的任何位置,然后在没有显式设置 GOROOT 的情况下使用。

默认情况下,go 工具会在系统临时目录(例如,Unix 上的 $TMPDIR)中创建其临时文件和目录。如果设置了新的环境变量 $GOTMPDIR,go 工具将在该目录中创建其临时文件和目录。

构建和安装

go build 命令现在仅根据源文件的内容、指定的构建标志和编译包中存储的元数据来检测过期的包。不再参考或考虑修改时间。过去建议在修改时间对某个原因(例如,构建标志中的更改)造成误导时,添加 -a 来强制重新构建的建议不再需要:构建现在始终检测何时必须重建包。(如果您观察到这种情况,请提交一个错误报告。)

go build-asmflags-gcflags-gccgoflags-ldflags 选项现在默认情况下仅应用于命令行上直接列出的包。例如,go build -gcflags=-m mypkg 在构建 mypkg 时向编译器传递 -m 标志,但不会向其依赖项传递该标志。新的更通用的形式 -asmflags=pattern=flags(以及类似的其他形式)仅将 flags 应用于与模式匹配的包。例如:go install -ldflags=cmd/gofmt=-X=main.version=1.2.3 cmd/... 安装所有与 cmd/... 匹配的命令,但仅将 -X 选项应用于 cmd/gofmt 的链接器标志。有关更多详细信息,请参阅 go help build

go build 命令现在维护一个最近构建的包的缓存,与 $GOROOT/pkg$GOPATH/pkg 中的已安装包分开。缓存的效果应该可以加快没有显式安装包的构建,或者在切换不同的源代码副本(例如,在版本控制系统中来回切换不同的分支)时加快构建速度。过去建议为了速度而添加 -i 标志(例如,go build -igo test -i)的建议不再需要:构建在没有 -i 的情况下运行速度一样快。有关更多详细信息,请参阅 go help cache

go install 命令现在仅安装命令行上直接列出的包和命令。例如,go install cmd/gofmt 安装 gofmt 程序,但不安装其依赖的任何包。新的构建缓存使得将来的命令仍然可以像安装依赖项一样快地运行。要强制安装依赖项,请使用新的 go install -i 标志。通常情况下,不应该需要安装依赖项包,并且已安装包的概念可能会在将来的版本中消失。

go build 实现的许多细节都已更改以支持这些改进。这些更改暗示的一个新要求是,现在仅包含二进制文件的包必须在其存根源代码中声明准确的导入块,以便在使用仅包含二进制文件的包链接程序时,可以提供这些导入。有关更多详细信息,请参阅 go help filetype

测试

go test 命令现在缓存测试结果:如果测试可执行文件和命令行与之前运行的匹配,并且该运行所参考的文件和环境变量也没有更改,go test 将打印之前的测试输出,并将经过的时间替换为字符串“(cached)”。测试缓存仅适用于成功的测试结果;仅适用于具有显式包列表的 go test 命令;并且仅适用于使用 -cpu-list-parallel-run-short-v 测试标志子集的命令行。绕过测试缓存的惯用方法是使用 -count=1

go test 命令现在会自动对正在测试的包运行 go vet,以便在运行测试之前识别出重大问题。任何此类问题都被视为构建错误,并阻止测试执行。仅对可用的 go vet 检查中的一小部分高置信度检查启用此自动检查。要禁用运行 go vet,请使用 go test -vet=off

go test -coverpkg 标志现在将它的参数解释为一个逗号分隔的模式列表,用于匹配每个测试的依赖项,而不是一个要重新加载的包列表。例如,go test -coverpkg=all 现在是一种有意义的方法,可以运行启用覆盖率的测试,以涵盖测试包及其所有依赖项。此外,在运行多个测试时,现在支持 go test -coverprofile 选项。

如果由于超时而导致失败,测试现在更有可能在退出之前写入其配置文件。

go test 命令现在始终合并给定测试二进制文件执行的标准输出和标准错误,并将两者写入 go test 的标准输出。在过去的版本中,go test 仅在大多数情况下应用此合并。

go test -v 输出现在包含 PAUSECONT 状态更新行,用于标记 并行测试 何时暂停和继续。

新的 go test -failfast 标志在任何测试失败后都会禁用运行其他测试。请注意,与失败测试并行运行的测试可以完成。

最后,新的 go test -json 标志通过新的命令 go tool test2json 过滤测试输出,以生成测试执行的机器可读 JSON 格式描述。这允许在 IDE 和其他工具中创建丰富的测试执行演示。

有关所有这些变更的更多详细信息,请参阅 go help testtest2json 文档

Cgo

使用 #cgo CFLAGS 等方式由 cgo 指定的选项现在将与允许的选项列表进行检查。这将关闭一个安全漏洞,在该漏洞中,下载的包使用诸如 -fplugin 之类的编译器选项在构建该包的机器上运行任意代码。这可能会导致构建错误,例如 #cgo CFLAGS 中的无效标志。有关更多背景信息以及如何处理此错误,请参阅 https://golang.ac.cn/s/invalidflag

cgo 现在使用 Go 类型别名实现类似“typedef X Y”的 C typedef,以便 Go 代码可以互换使用类型 C.XC.Y。它现在还支持使用无参函数式宏。此外,文档已更新以澄清,Go 结构体和 Go 数组在 cgo 导出函数的类型签名中不受支持。

cgo 现在支持从 C 直接访问 Go 字符串值。C 前置声明中的函数可以使用类型 _GoString_ 来接受 Go 字符串作为参数。C 代码可以调用 _GoStringLen_GoStringPtr 来直接访问字符串的内容。类型为 _GoString_ 的值可以在调用导出 Go 函数时传递,该函数接受 Go 类型 string 的参数。

在工具链引导期间,环境变量 CCCC_FOR_TARGET 分别指定了生成的工具链将用于主机和目标构建的默认 C 编译器。但是,如果工具链将用于多个目标,则可能需要为每个目标指定不同的 C 编译器(例如,为 darwin/arm64linux/ppc64le 指定不同的编译器)。新的环境变量集 CC_FOR_goos_goarch 允许为每个目标指定不同的默认 C 编译器。请注意,这些变量仅在工具链引导期间应用,以设置生成的工具链使用的默认值。以后的 go build 命令使用 CC 环境变量,或者使用内置的默认值。

cgo 现在将一些 C 类型(这些类型通常会映射到 Go 中的指针类型)转换为 uintptr。这些类型包括 Darwin 的 CoreFoundation 框架中的 CFTypeRef 层次结构和 Java 的 JNI 接口中的 jobject 层次结构。

这些类型必须在 Go 端为 uintptr,因为否则它们会混淆 Go 垃圾收集器;它们有时不是真正的指针,而是以指针大小的整数编码的数据结构。指向 Go 内存的指针不得存储在这些 uintptr 值中。

由于此更改,受影响类型的值需要使用常量 0 初始化为零,而不是常量 nil。Go 1.10 提供了 gofix 模块来帮助进行该重写。

go tool fix -r cftype <pkg>
go tool fix -r jni <pkg>

有关更多详细信息,请参阅 cgo 文档

文档

go doc 工具现在将返回类型为 T*T 的切片的函数添加到类型 T 的显示中,类似于对返回单个 T*T 结果的函数的现有行为。例如

$ go doc mail.Address
package mail // import "net/mail"

type Address struct {
    Name    string
    Address string
}
    Address represents a single mail address.

func ParseAddress(address string) (*Address, error)
func ParseAddressList(list string) ([]*Address, error)
func (a *Address) String() string
$

以前,ParseAddressList 仅在包概述(go doc mail)中显示。

修复

go fix 工具现在将 "golang.org/x/net/context" 的导入替换为 "context"。(前者的转发别名使其在使用 Go 1.9 或更高版本时与后者完全等效。)

获取

go get 命令现在支持 Fossil 源代码仓库。

Pprof

runtime/pprof 包生成的阻塞和互斥锁配置文件现在包含符号信息,因此可以在 go tool pprof 中查看它们,而无需生成该配置文件的二进制文件。(所有其他配置文件类型已在 Go 1.9 中更改为包含符号信息。)

go tool pprof 配置文件可视化器已更新到 git 版本 9e20b5b(2017-11-08),来自 github.com/google/pprof,其中包含更新的 Web 界面。

Vet

go vet 命令现在始终能够在检查包时访问完整、最新的类型信息,即使对于使用 cgo 或供应商导入的包也是如此。因此,报告应该更加准确。请注意,只有 go vet 能够访问此信息;更低级的 go tool vet 不能访问此信息,应避免使用它,除非在处理 vet 本身时。 (从 Go 1.9 开始,go vet 提供对与 go tool vet 相同的所有标志的访问。)

诊断

此版本包含一个新的 可用的 Go 程序诊断工具概述

Gofmt

Go 源代码的默认格式有两个次要细节已更改。首先,某些复杂的三个索引切片表达式以前格式为 x[i+1 : j:k],现在以更一致的间距格式化:x[i+1 : j : k]。其次,在一行上编写的单方法接口字面量(有时在类型断言中使用)不再拆分到多行。

请注意,这些对 gofmt 的次要更新预计会不时出现。一般而言,我们建议不要构建检查源代码是否与特定版本 gofmt 的输出相匹配的系统。例如,如果任何已检入存储库的代码未“正确格式化”,则连续集成测试就会失败,这种测试本质上是脆弱的,不建议使用。

如果多个程序必须就使用哪个版本的 gofmt 来格式化源文件达成一致,我们建议它们通过安排调用相同的 gofmt 二进制文件来实现这一点。例如,在 Go 开源存储库中,我们的 Git 预提交钩子是用 Go 编写的,可以直接导入 go/format,但它会调用当前路径中找到的 gofmt 二进制文件,因此预提交钩子不必每次 gofmt 更改时都重新编译。

编译器工具链

编译器包含许多对生成代码性能的改进,这些改进相当均匀地分布在所有支持的体系结构中。

二进制文件中记录的 DWARF 调试信息已通过以下几种方式进行了改进:现在记录常量值;行号信息更加准确,使通过程序进行源代码级单步执行效果更好;现在每个包都作为其自己的 DWARF 编译单元呈现。

各种 构建模式已移植到更多系统。具体而言,c-shared 现在可以在 linux/ppc64lewindows/386windows/amd64 上运行;pie 现在可以在 darwin/amd64 上运行,并且还在所有系统上强制使用外部链接;plugin 现在可以在 linux/ppc64ledarwin/amd64 上运行。

linux/ppc64le 端口现在要求使用外部链接,适用于使用 cgo 的任何程序,即使是标准库的使用也是如此。

汇编器

对于 ARM 32 位端口,汇编器现在支持 BFCBFIBFXBFXUFMULADFMULAFFMULSDFMULSFFNMULADFNMULAFFNMULSDFNMULSFMULADMULAFMULSDMULSFNMULADNMULAFNMULDNMULFNMULSDNMULSFXTABXTABUXTAHXTAHU 指令。

对于 ARM 64 位端口,汇编器现在支持 VADDVADDPVADDVVANDVCMEQVDUPVEORVLD1VMOVVMOVIVMOVSVORRVREV32VST1 指令。

对于 PowerPC 64 位端口,汇编器现在支持 POWER9 指令 ADDEXCMPEQBCOPYDARNLDMXMADDHDMADDHDUMADDLDMFVSRLDMTVSRDDMTVSRWSPASTECCVCMPNEZBVCMPNEZBCCVMSUMUDM

对于 S390X 端口,汇编器现在支持 TMHHTMHLTMLHTMLL 指令。

对于 X86 64 位端口,汇编器现在支持 359 条新指令,包括完整的 AVX、AVX2、BMI、BMI2、F16C、FMA3、SSE2、SSE3、SSSE3、SSE4.1 和 SSE4.2 扩展集。汇编器也不再实现 MOVL $0, AX 作为 XORL 指令,以避免意外清除条件标志。

Gccgo

由于 Go 的半年发布计划与 GCC 的年度发布计划一致,GCC 版本 7 包含 Go 1.8.3 版本的 gccgo。我们预计下一个版本 GCC 8 将包含 Go 1.10 版本的 gccgo。

运行时

LockOSThreadUnlockOSThread 的嵌套调用的行为进行了更改。这些函数控制 goroutine 是否锁定到特定的操作系统线程,以便 goroutine 仅在该线程上运行,而该线程仅运行该 goroutine。以前,在同一行调用 LockOSThread 多次等效于调用一次,而单个 UnlockOSThread 始终解锁线程。现在,调用会嵌套:如果多次调用 LockOSThread,则必须调用相同次数的 UnlockOSThread 才能解锁线程。现有的代码如果小心地不嵌套这些调用,则会保持正确。现有的代码如果错误地假设调用嵌套,则会变得正确。公共 Go 源代码中这些函数的大多数使用都属于第二类。

因为 LockOSThreadUnlockOSThread 的一个常见用途是允许 Go 代码可靠地修改线程本地状态(例如,Linux 或 Plan 9 命名空间),因此运行时现在将锁定线程视为不适合重用或创建新线程。

堆栈跟踪不再包含隐式包装器函数(以前标记为 <autogenerated>),除非故障或恐慌发生在包装器本身中。因此,传递给诸如 Caller 之类的函数的跳过计数现在应该始终匹配代码的结构,而不是取决于优化决策和实现细节。

垃圾收集器已修改以减少其对分配延迟的影响。它现在在运行时使用较小的 CPU 比例,但它可能运行的时间更长。垃圾收集器消耗的总 CPU 时间没有明显变化。

GOROOT 函数现在默认为(当未设置 $GOROOT 环境变量时)编译调用程序时有效的 GOROOTGOROOT_FINAL。以前它使用编译调用程序的工具链时有效的 GOROOTGOROOT_FINAL

GOMAXPROCS 设置不再有任何限制。(在 Go 1.9 中,限制为 1024。)

性能

与往常一样,这些更改非常普遍,因此很难做出关于性能的精确陈述。由于垃圾收集器的加速、更好的代码生成和核心库中的优化,大多数程序应该运行得更快一些。

垃圾收集器

当垃圾收集器处于活动状态时,许多应用程序应该会遇到明显更低的分配延迟和整体性能开销。

标准库

标准库的所有更改都是微小的。在字节net/url中的更改最有可能需要更新现有程序。

库的微小更改

与往常一样,库中存在各种微小的更改和更新,这些更改和更新是在考虑 Go 1 的兼容性承诺的情况下进行的。

archive/tar

总的来说,对特殊标头格式的处理得到了显著改进和扩展。

FileInfoHeader始终从其os.FileInfo参数(具体来说,从FileInfoSys方法返回的系统相关信息)中记录返回的Header中的 Unix UID 和 GID 编号。现在,它还记录与这些 ID 相对应的用户和组名称,以及设备文件的 major 和 minor 设备编号。

类型为Format的新Header.Format字段控制Writer使用的 tar 标头格式。与之前一样,默认情况下,选择最广泛支持的标头类型,该类型可以对标头所需的字段进行编码(如果可能,则为 USTAR,否则为 PAX,否则为 GNU)。Reader为其读取的每个标头设置Header.Format

ReaderWriter现在使用新的Header.PAXRecords字段支持任意 PAX 记录,它是现有Xattrs字段的推广。

Reader不再坚持 GNU 标头中的文件名或链接名必须是有效的 UTF-8。

在写入 PAX 或 GNU 格式的标头时,Writer现在将包含Header.AccessTimeHeader.ChangeTime字段(如果已设置)。在写入 PAX 格式的标头时,时间将包含亚秒精度。

archive/zip

Go 1.10 为 ZIP 存档中的时间和字符集编码添加了更完整的支持。

原始 ZIP 格式使用标准的 MS-DOS 编码将年、月、日、时、分、秒编码成两个 16 位值的字段中。该编码无法表示时区或奇数秒,因此引入了多个扩展以允许更丰富的编码。在 Go 1.10 中,ReaderWriter现在支持广泛理解的 Info-Zip 扩展,该扩展以 32 位 Unix“自纪元以来的秒”形式单独编码时间。类型为time.TimeFileHeader的新Modified字段使ModifiedTimeModifiedDate字段过时,这两个字段继续保留 MS-DOS 编码。ReaderWriter现在采用通用约定,即存储时区无关 Unix 时间的 ZIP 存档也将在 MS-DOS 字段中存储本地时间,以便可以推断出时区偏移量。为了兼容性,ModTimeSetModTime方法的行为与早期版本相同;新代码应该直接使用Modified

ZIP 存档中每个文件的标头都有一个标志位,指示名称和注释字段是否编码为 UTF-8,而不是系统特定的默认编码。在 Go 1.8 及更早版本中,Writer从不设置 UTF-8 位。在 Go 1.9 中,Writer更改为几乎总是设置 UTF-8 位。这破坏了创建包含 Shift-JIS 文件名的 ZIP 存档。在 Go 1.10 中,Writer现在仅在名称和注释字段都是有效的 UTF-8 且至少有一个是非 ASCII 时才设置 UTF-8 位。由于非 ASCII 编码很少看起来像有效的 UTF-8,因此新的启发式方法应该在几乎所有时间都是正确的。将FileHeader的新NonUTF8字段设置为 true 将完全禁用该启发式方法,以针对该文件。

Writer现在还支持通过调用Writer的新SetComment方法来设置中央目录记录末尾的注释字段。

bufio

新的Reader.SizeWriter.Size方法报告ReaderWriter的底层缓冲区大小。

bytes

FieldsFieldsFuncSplitSplitAfter函数始终返回其输入的子切片。Go 1.10 将每个返回的子切片更改为具有等于其长度的容量,以便向其附加不会覆盖原始输入中的相邻数据。

crypto/cipher

NewOFB现在在给出长度不正确的初始化向量时会引发恐慌,就像包中的其他构造函数一直以来的行为一样。(以前它返回一个为 nil 的Stream实现。)

crypto/tls

TLS 服务器现在在使用 TLS 1.2 时会宣传对 SHA-512 签名的支持。服务器已经支持签名,但某些客户端除非明确宣传,否则不会选择它们。

crypto/x509

Certificate.Verify现在会对证书中包含的所有名称(而不仅仅是客户端询问的名称)强制执行名称约束。扩展密钥使用限制也同样一次性检查。因此,在验证证书后,现在可以完全信任它。无需针对每个额外的名称或密钥使用重新验证证书。

解析的证书现在还使用新的Certificate字段URIsPermittedIPRangesExcludedIPRangesPermittedEmailAddressesExcludedEmailAddressesPermittedURIDomainsExcludedURIDomains来报告 URI 名称以及 IP、电子邮件和 URI 约束。现在将拒绝具有这些字段无效值的证书。

新的MarshalPKCS1PublicKeyParsePKCS1PublicKey函数将 RSA 公钥转换为 PKCS#1 编码形式,反之亦然。

新的MarshalPKCS8PrivateKey函数将私钥转换为 PKCS#8 编码形式。(ParsePKCS8PrivateKey自 Go 1 起就存在。)

crypto/x509/pkix

Name现在实现了String方法,该方法以标准的 RFC 2253 格式格式化 X.509 区分名称。

database/sql/driver

目前保留driver.Rows.Next提供的目标缓冲区的驱动程序应确保不再写入分配给目标数组的缓冲区,除非该调用之外。驱动程序必须注意,在关闭driver.Rows时,不会修改底层缓冲区。

想要为其客户端构建sql.DB的驱动程序现在可以实现Connector接口并调用新的sql.OpenDB函数,而不是需要将所有配置编码到传递给sql.Open的字符串中。

想要对每个sql.DB仅解析一次配置字符串,而不是对每个sql.Conn解析一次,或者想要访问每个sql.Conn的底层上下文的驱动程序可以使其Driver实现也实现DriverContext的新OpenConnector方法。

实现ExecerContext的驱动程序不再需要实现Execer;类似地,实现QueryerContext的驱动程序不再需要实现Queryer。以前,即使实现了基于上下文的接口,除非也实现了非基于上下文的接口,否则它们会被忽略。

为了允许驱动程序更好地隔离使用缓存的驱动程序连接连续地使用不同客户端,如果Conn实现了新的SessionResetter接口,database/sql现在将在为新客户端重用Conn之前调用ResetSession

debug/elf

此版本添加了 348 个新的重定位常量,这些常量分布在重定位类型R_386R_AARCH64R_ARMR_PPC64R_X86_64之间。

debug/macho

Go 1.10 添加了对从 Mach-O 部分读取重定位的支持,使用Section结构的新Relocs字段以及新的RelocRelocTypeARMRelocTypeARM64RelocTypeGenericRelocTypeX86_64类型以及相关的常量。

Go 1.10 还添加了对LC_RPATH加载命令的支持,该命令由类型RpathCmdRpath表示,以及新的命名常量,用于在标头中找到的各种标志位。

encoding/asn1

Marshal现在可以正确地将包含星号的字符串编码为 UTF8String 类型,而不是 PrintableString 类型,除非该字符串位于具有强制使用 PrintableString 的标签的结构字段中。Marshal现在还尊重包含application指令的结构标签。

新的MarshalWithParams函数像额外的参数是其关联的结构字段标签一样封送其参数。

Unmarshal现在尊重使用explicittag指令的结构字段标签。

MarshalUnmarshal现在都支持新的结构字段标签numeric,指示 ASN.1 NumericString。

encoding/csv

Reader现在不允许使用无意义的CommaComment设置,例如 NUL、回车符、换行符、无效的 rune 以及 Unicode 替换字符,或将CommaComment设置成相等。

在跨多个输入行的 CSV 记录中出现语法错误的情况下,Reader现在将在ParseError的新StartLine字段中报告记录开始的行。

encoding/hex

新的函数 NewEncoderNewDecoder 提供了与十六进制之间的流式转换,类似于 encoding/base32encoding/base64 中已有的等效函数。

当函数 DecodeDecodeString 遇到格式错误的输入时,它们现在会返回已转换的字节数以及错误。以前它们总是返回 0 的计数,以及任何错误。

encoding/json

Decoder 添加了一个新方法 DisallowUnknownFields,该方法会使它将具有未知 JSON 字段的输入报告为解码错误。(默认行为一直是丢弃未知字段。)

由于 修复了 reflect 错误Unmarshal 现在无法再解码到嵌入到未导出结构类型指针中的字段中,因为它无法初始化未导出的嵌入指针以指向新的存储空间。Unmarshal 现在在此情况下会返回错误。

encoding/pem

EncodeEncodeToMemory 现在不再在遇到无法编码为 PEM 数据的块时生成部分输出。

encoding/xml

新函数 NewTokenDecoder 类似于 NewDecoder,但它创建了一个从 TokenReader 而不是 XML 格式的字节流中读取的解码器。这旨在使客户端库能够构建 XML 流转换器。

flag

默认的 Usage 函数现在将它的第一行输出打印到 CommandLine.Output() 而不是假设 os.Stderr,因此使用消息将被正确地重定向,用于使用 CommandLine.SetOutput 的客户端。

PrintDefaults 现在在标志使用字符串中的换行符之后添加了适当的缩进,以便多行使用字符串可以很好地显示。

FlagSet 添加了新方法 ErrorHandlingNameOutput,用于检索传递给 NewFlagSetFlagSet.SetOutput 的设置。

go/doc

为了支持上面描述的 doc 更改,现在在 TTypeFuncs 列表中报告返回 T*T**T 等等切片的函数,而不是在 PackageFuncs 列表中。

go/importer

For 函数现在接受非空的 lookup 参数。

go/printer

上面 gofmt 部分 中讨论的关于 Go 源代码的默认格式的更改在 go/printer 包中实现,并且也影响了更高级别的 go/format 包的输出。

hash

现在鼓励 Hash 接口的实现来实现 encoding.BinaryMarshalerencoding.BinaryUnmarshaler,以允许保存和重新创建它们的内部状态,并且标准库中的所有实现(hash/crc32crypto/sha256 等等)现在都实现了这些接口。

html/template

新的 Srcset 内容类型允许正确处理 srcset 属性(在 img 标签中)的值。

math/big

Int 现在支持在它的 SetStringText 方法中进行 2 到 62 进制之间的转换。(以前它只允许 2 到 36 进制。)常量 MaxBase 的值已更新。

Int 添加了一个新方法 CmpAbs,它类似于 Cmp,但只比较其参数的绝对值(不比较符号)。

Float 添加了一个新方法 Sqrt,用于计算平方根。

math/cmplx

AsinAsinhAtanSqrt 中的分支切割和其他边界情况已被纠正,以匹配 C99 标准中使用的定义。

math/rand

新函数 Shuffle 和相应的 Rand.Shuffle 方法会对输入序列进行洗牌。

math

新函数 RoundRoundToEven 会将其参数舍入到最接近的浮点数整数;Round 会将半个整数舍入到其更大的整数邻居(远离零),而 RoundToEven 会将半个整数舍入到其偶数整数邻居。

新函数 ErfinvErfcinv 计算逆误差函数和逆补误差函数。

mime/multipart

Reader 现在接受带有空文件名属性的部分。

mime

ParseMediaType 现在会丢弃无效的属性值;以前它会将这些值返回为空字符串。

net

此包中的 ConnListener 实现现在保证,当 Close 返回时,底层文件描述符已关闭。(在早期版本中,如果 Close 停止了其他 goroutine 中的挂起 I/O,文件描述符的关闭可能会在 Close 返回后不久的其中一个 goroutine 中发生。)

TCPListenerUnixListener 现在实现了 syscall.Conn,以允许使用 syscall.RawConn.Control 在底层文件描述符上设置选项。

Pipe 返回的 Conn 实现现在支持设置读和写截止日期。

IPConn.ReadMsgIPIPConn.WriteMsgIPUDPConn.ReadMsgUDPUDPConn.WriteMsgUDP 方法现在在 Windows 上实现。

net/http

在客户端方面,HTTP 代理(最常由 ProxyFromEnvironment 配置)现在可以指定为 https:// URL,这意味着客户端通过 HTTPS 连接到代理,然后发出标准的代理 HTTP 请求。(以前,HTTP 代理 URL 要求以 http://socks5:// 开头。)

在服务器方面,FileServer 及其单文件等效项 ServeFile 现在将 If-Range 检查应用于 HEAD 请求。FileServer 现在还会将目录读取失败报告给 ServerErrorLog。内容提供处理程序现在还将在提供零长度内容时省略 Content-Type 标头。

ResponseWriterWriteHeader 方法现在在传递无效(非 3 位数)状态代码时会引发恐慌。

Server 将不再在 Handler 未写入任何输出时添加隐式 Content-Type。

Redirect 现在在写入其 HTTP 响应之前设置 Content-Type 标头。

net/mail

ParseAddressParseAddressList 现在支持各种过时的地址格式。

net/smtp

Client 添加了一个新方法 Noop,用于测试服务器是否仍在响应。它现在还防御可能在 HelloVerify 方法的输入中出现的 SMTP 注入。

net/textproto

ReadMIMEHeader 现在拒绝任何以续行(缩进)标头行开头的标头。以前,带有缩进第一行的标头会被当作没有缩进第一行来处理。

net/url

ResolveReference 现在保留目标 URL 中的多个前导斜杠。以前它会将多个前导斜杠重写为单个斜杠,这会导致 http.Client 错误地遵循某些重定向。

例如,这段代码的输出已更改

base, _ := url.Parse("http://host//path//to/page1")
target, _ := url.Parse("page2")
fmt.Println(base.ResolveReference(target))

请注意 path 周围的双斜杠。在 Go 1.9 及更早版本中,解析后的 URL 是 http://host/path//to/page2path 之前的双斜杠被错误地重写为单个斜杠,而 path 之后的双斜杠被正确地保留。Go 1.10 保留了这两个双斜杠,根据 RFC 3986 的要求解析为 http://host//path//to/page2

此更改可能会破坏现有的错误程序,这些程序无意中构建了一个在路径中带有前导双斜杠的基 URL,并无意中依赖 ResolveReference 来纠正该错误。例如,如果代码将主机前缀(如 http://host/)添加到路径(如 /my/api)中,就会导致 URL 带有双斜杠:http://host//my/api

UserInfo 的方法现在将 nil 接收器视为等同于指向零 UserInfo 的指针。以前,它们会引发恐慌。

os

File 添加了新方法 SetDeadlineSetReadDeadlineSetWriteDeadline,这些方法允许在底层文件描述符支持非阻塞 I/O 操作时设置 I/O 截止日期。这些方法的定义与 net.Conn 中的定义匹配。如果 I/O 方法由于错过截止日期而失败,它将返回超时错误;新的 IsTimeout 函数会报告错误是否代表超时。

同样匹配 net.ConnFileClose 方法现在保证,当 Close 返回时,底层文件描述符已关闭。(在早期版本中,如果 Close 停止了其他 goroutine 中的挂起 I/O,文件描述符的关闭可能会在 Close 返回后不久的其中一个 goroutine 中发生。)

在 BSD、macOS 和 Solaris 系统上,Chtimes 现在支持使用纳秒精度设置文件时间(假设底层文件系统可以表示它们)。

reflect

Copy 函数现在允许从字符串复制到字节数组或字节切片中,以匹配 内置的 copy 函数

在结构体中,嵌入指向未导出结构体类型的指针以前被错误地报告为在相应的 StructField 中具有空的 PkgPath,导致这些字段的 Value.CanSet 错误地返回 true,而 Value.Set 错误地成功。底层元数据已更正;对于这些字段,CanSet 现在将正确地返回 false,而 Set 现在将正确地引发恐慌。这可能会影响以前能够解组到这些字段但现在不能的基于反射的解组器。例如,请参阅 encoding/json 说明

runtime/pprof

上文所述,阻塞和互斥锁配置文件现在包含符号信息,因此可以在无需生成它们的二进制文件的情况下查看它们。

strconv

ParseUint 现在返回适当大小的最大幅度整数,以及任何 ErrRange 错误,因为它已经在文档中说明了这一点。以前它返回 0,并带 ErrRange 错误。

strings

新类型 Builderbytes.Buffer 的替代方案,用于将文本累积到 string 结果中。Builder 的 API 是 bytes.Buffer 的一个受限子集,它允许它在 String 方法期间安全地避免对数据进行重复复制。

syscall

在 Windows 上,新 SysProcAttr 字段 Token(类型为 Token)允许创建在 StartProcess(因此也在 os.StartProcessexec.Cmd.Start 中)运行为其他用户的进程。新函数 CreateProcessAsUser 提供对底层系统调用的访问权限。

在 BSD、macOS 和 Solaris 系统上,现在实现了 UtimesNano

time

LoadLocation 现在在默认的系统特定已知安装位置列表或 $GOROOT/lib/time/zoneinfo.zip 中查找之前,使用由 $ZONEINFO 环境变量命名的目录或解压缩的 zip 文件。

新函数 LoadLocationFromTZData 允许将 IANA 时区文件数据转换为 Location

unicode

整个系统中的 unicode 包和相关支持已从 Unicode 9.0 升级到 Unicode 10.0,增加了 8,518 个新字符,包括四个新脚本、一个新属性、一个比特币货币符号和 56 个新的表情符号。