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

Test

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

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

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

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

Cgo 现在将某些通常映射到 Go 中指针类型的 C 类型转换为 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 配置文件可视化工具已从 github.com/google/pprof 更新到 git 版本 9e20b5b (2017-11-08),其中包括一个更新的 Web 界面。

Vet

go vet 命令现在在检查包时总是能访问到完整的、最新的类型信息,即使对于使用 cgo 或 vendored 导入的包也是如此。因此,报告应该更准确。请注意,只有 go vet 才能访问此信息;更底层的 go tool vet 没有,除了在处理 vet 本身时应避免使用。(从 Go 1.9 开始,go vet 提供了与 go tool vet 相同的所有标志的访问权限。)

Diagnostics

此版本包含一份新的可用 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。)

性能

一如既往,这些变化是如此普遍和多样,以至于很难对性能做出精确的说明。由于垃圾回收器的加速、更好的生成代码以及核心库中的优化,大多数程序应该运行得更快一些。

垃圾收集器

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

标准库

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

对库的微小更改

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

archive/tar

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

FileInfoHeader 始终将其 os.FileInfo 参数中的 Unix UID 和 GID 数字(特别是从 FileInfoSys 方法返回的系统相关信息)记录到返回的 Header 中。现在,它还记录了与这些 ID 对应的用户和组名,以及设备文件的主设备号和次设备号。

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

ReaderWriter 现在支持任意 PAX 记录,使用新的 Header.PAXRecords 字段,这是现有 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“自纪元以来的秒数”形式单独编码时间。FileHeader 的新 Modified 字段类型为 time.Time,它淘汰了 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.Sizebytes

FieldsFieldsFuncSplitSplitAfter 函数始终返回其输入的子切片。Go 1.10 将每个返回的子切片的容量更改为与其长度相等,这样追加到一个子切片就不会覆盖原始输入中相邻的数据。

crypto/cipher

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

crypto/tls

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

crypto/x509

Certificate.Verify 现在会强制执行证书中所有名称的名称约束,而不仅仅是客户端查询的单个名称。扩展密钥用法限制也同样一次性检查。因此,证书验证后,现在可以完全信任它。不再需要为每个附加名称或密钥用法重新验证证书。

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

新的 MarshalPKCS1PublicKeyParsePKCS1PublicKey 函数将 RSA 公钥转换为 PKCS#1 编码形式并从 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 的驱动程序不再需要实现 Conn 实现了新的 SessionResetter 接口,则 database/sql 现在将在为新客户端重用 Conn 之前调用 ResetSession

debug/elf

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

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、回车、换行、无效符文和 Unicode 替换字符,或者将 CommaComment 设置为彼此相等。

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

encoding/hex

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

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

encoding/json

Decoder 添加了一个新方法 DisallowUnknownFields,它会导致在解码时将带有未知 JSON 字段的输入报告为解码错误。(默认行为始终是丢弃未知字段。)

由于修复了一个反射 bugUnmarshal 不再能够解码到嵌入式指向未导出结构体类型的指针中的字段,因为它无法初始化未导出的嵌入式指针以指向新存储。在这种情况下,Unmarshal 现在会返回一个错误。

encoding/pem

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

encoding/xml

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

flag

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

PrintDefaults 现在会在标志用法字符串中的换行符后添加适当的缩进,以便多行用法字符串显示得更好。

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

go/doc

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

go/importer

For 函数现在接受非 nil 的查找参数。

go/printer

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

hash

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

html/template

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

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 位数)状态码时会发生 panic。

Handler 不写入任何输出时,Server 将不再添加隐式 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 保留了两个双斜杠,解析为 http://host//path//to/page2,正如 RFC 3986 所要求的。

此更改可能会破坏现有有缺陷的程序,这些程序无意中构建了在路径中具有前导双斜杠的基 URL,并且无意中依赖 ResolveReference 来纠正该错误。例如,如果代码将 http://host/ 等主机前缀添加到 /my/api 等路径,则可能发生这种情况,从而导致 URL 出现双斜杠:http://host//my/api

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

os

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

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

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

reflect

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

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

runtime/pprof

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

strconv

ParseUint 现在会与任何 ErrRange 错误一起返回适当大小的最大幅值整数,正如其文档所述。以前它会与 ErrRange 错误一起返回 0。

strings

一种新类型 Builder 取代了 bytes.Buffer 用于将文本累积到 string 结果的用例。Builder 的 API 是 bytes.Buffer 的一个受限子集,它允许在 String 方法期间安全地避免创建数据的重复副本。

syscall

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

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

time

LoadLocation 现在会先使用 $ZONEINFO 环境变量指定的目录或未压缩的 zip 文件,然后再查找已知安装位置的默认系统特定列表或 $GOROOT/lib/time/zoneinfo.zip

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

unicode

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