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
amd64
和 386
已修复。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
-i
或 go
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
输出现在包含 PAUSE
和 CONT
状态更新行,用于标记并行测试何时暂停和继续。
新的 go
test
-failfast
标志在任何测试失败后禁用运行其他测试。请注意,允许与失败测试并行运行的测试完成。
最后,新的 go
test
-json
标志通过新的命令 go
tool
test2json
过滤测试输出,以生成机器可读的 JSON 格式的测试执行描述。这允许在 IDE 和其他工具中创建丰富的测试执行演示。
有关所有这些更改的更多详细信息,请参阅 go
help
test
和 test2json 文档。
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.X
和 C.Y
类型。它现在还支持使用无参数函数式宏。此外,文档已更新,以澄清 cgo 导出函数的类型签名中不支持 Go 结构体和 Go 数组。
Cgo 现在支持从 C 直接访问 Go 字符串值。C 前导码中的函数可以使用 _GoString_
类型来接受 Go 字符串作为参数。C 代码可以调用 _GoStringLen
和 _GoStringPtr
来直接访问字符串内容。类型为 _GoString_
的值可以在调用接受 Go 类型 string
参数的导出 Go 函数时传递。
在工具链引导期间,环境变量 CC
和 CC_FOR_TARGET
分别指定生成工具链将用于主机和目标构建的默认 C 编译器。但是,如果工具链将与多个目标一起使用,则可能需要为每个目标指定不同的 C 编译器(例如,darwin/arm64
与 linux/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/ppc64le
、windows/386
和 windows/amd64
上工作;pie
现在可以在 darwin/amd64
上工作,并且在所有系统上强制使用外部链接;plugin
现在可以在 linux/ppc64le
和 darwin/amd64
上工作。
linux/ppc64le
端口现在要求所有使用 cgo 的程序(即使是标准库使用的程序)都必须使用外部链接。
汇编器
对于 ARM 32 位端口,汇编器现在支持 BFC
、BFI
、BFX
、BFXU
、FMULAD
、FMULAF
、FMULSD
、FMULSF
、FNMULAD
、FNMULAF
、FNMULSD
、FNMULSF
、MULAD
、MULAF
、MULSD
、MULSF
、NMULAD
、NMULAF
、NMULD
、NMULF
、NMULSD
、NMULSF
、XTAB
、XTABU
、XTAH
和 XTAHU
指令。
对于 ARM 64 位端口,汇编器现在支持 VADD
、VADDP
、VADDV
、VAND
、VCMEQ
、VDUP
、VEOR
、VLD1
、VMOV
、VMOVI
、VMOVS
、VORR
、VREV32
和 VST1
指令。
对于 PowerPC 64 位端口,汇编器现在支持 POWER9 指令 ADDEX
、CMPEQB
、COPY
、DARN
、LDMX
、MADDHD
、MADDHDU
、MADDLD
、MFVSRLD
、MTVSRDD
、MTVSRWS
、PASTECC
、VCMPNEZB
、VCMPNEZBCC
和 VMSUMUDM
。
对于 S390X 端口,汇编器现在支持 TMHH
、TMHL
、TMLH
和 TMLL
指令。
对于 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。
运行时
LockOSThread
和 UnlockOSThread
的嵌套调用行为已更改。这些函数控制 goroutine 是否锁定到特定的操作系统线程,以便 goroutine 只在该线程上运行,并且该线程只运行该 goroutine。以前,连续多次调用 LockOSThread
等同于调用一次,并且单个 UnlockOSThread
总是解锁线程。现在,调用是嵌套的:如果多次调用 LockOSThread
,则必须调用相同次数的 UnlockOSThread
才能解锁线程。现有代码如果小心不嵌套这些调用,将保持正确。现有代码如果错误地假设调用是嵌套的,将变得正确。公共 Go 源代码中这些函数的大多数用法都属于第二类。
由于 LockOSThread
和 UnlockOSThread
的一个常见用途是允许 Go 代码可靠地修改线程本地状态(例如,Linux 或 Plan 9 命名空间),因此运行时现在将锁定的线程视为不适合重用或创建新线程。
除非在包装器本身发生故障或恐慌,否则堆栈跟踪不再包含隐式包装器函数(以前标记为 <autogenerated>
)。因此,传递给 Caller
等函数的跳过计数现在应该总是与所编写代码的结构匹配,而不是依赖于优化决策和实现细节。
垃圾回收器已修改,以减少其对分配延迟的影响。它现在在运行时使用的总体 CPU 比例更小,但运行时间可能更长。垃圾回收器消耗的总 CPU 没有显著变化。
GOROOT
函数现在默认(当未设置 $GOROOT
环境变量时)为调用程序编译时生效的 GOROOT
或 GOROOT_FINAL
。以前它使用编译调用程序的工具链编译时生效的 GOROOT
或 GOROOT_FINAL
。
对 GOMAXPROCS
设置不再有限制。(在 Go 1.9 中,限制为 1024。)
性能
一如既往,这些变化是如此普遍和多样,以至于很难对性能做出精确的说明。由于垃圾回收器的加速、更好的生成代码以及核心库中的优化,大多数程序应该运行得更快一些。
垃圾收集器
当垃圾回收器处于活动状态时,许多应用程序应该会经历显著更低的分配延迟和整体性能开销。
标准库
标准库的所有更改都是微小的。bytes 和 net/url 中的更改最有可能需要更新现有程序。
对库的微小更改
与往常一样,库中有各种微小的更改和更新,这些都是在遵守 Go 1 兼容性承诺的前提下进行的。
archive/tar
总的来说,对特殊头部格式的处理得到了显著的改进和扩展。
FileInfoHeader
始终将其 os.FileInfo
参数中的 Unix UID 和 GID 数字(特别是从 FileInfo
的 Sys
方法返回的系统相关信息)记录到返回的 Header
中。现在,它还记录了与这些 ID 对应的用户和组名,以及设备文件的主设备号和次设备号。
新的 Header.Format
字段类型为 Format
,控制 Writer
使用哪种 tar 头部格式。默认情况下,与以前一样,选择最广泛支持的头部类型,该类型可以编码头部所需的字段(如果可能,USTAR;否则,如果可能,PAX;否则,GNU)。Reader
为其读取的每个头部设置 Header.Format
。
Reader
和 Writer
现在支持任意 PAX 记录,使用新的 Header.PAXRecords
字段,这是现有 Xattrs
字段的泛化。
Reader
不再坚持 GNU 头部中的文件名或链接名必须是有效的 UTF-8。
在写入 PAX 或 GNU 格式的头部时,Writer
现在包含 Header.AccessTime
和 Header.ChangeTime
字段(如果设置)。在写入 PAX 格式的头部时,时间包括亚秒精度。
archive/zip
Go 1.10 为 ZIP 归档中的时间和字符集编码添加了更完整的支持。
原始 ZIP 格式使用标准的 MS-DOS 编码将年、月、日、时、分和秒编码到两个 16 位值中的字段。该编码不能表示时区或奇数秒,因此引入了多个扩展以允许更丰富的编码。在 Go 1.10 中,Reader
和 Writer
现在支持广泛理解的 Info-Zip 扩展,该扩展以 32 位 Unix“自纪元以来的秒数”形式单独编码时间。FileHeader
的新 Modified
字段类型为 time.Time
,它淘汰了 ModifiedTime
和 ModifiedDate
字段,这些字段继续保存 MS-DOS 编码。Reader
和 Writer
现在采用的常见约定是,存储与时区无关的 Unix 时间的 ZIP 归档也以 MS-DOS 字段存储本地时间,以便可以推断时区偏移。为了兼容性,ModTime
和 SetModTime
方法的行为与早期版本相同;新代码应直接使用 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.Size
和 bytes
Fields
、FieldsFunc
、Split
和 SplitAfter
函数始终返回其输入的子切片。Go 1.10 将每个返回的子切片的容量更改为与其长度相等,这样追加到一个子切片就不会覆盖原始输入中相邻的数据。
crypto/cipher
NewOFB
现在会在给定初始化向量长度不正确时发生 panic,就像该包中的其他构造函数一直以来那样。(以前它返回一个 nil Stream
实现。)
crypto/tls
TLS 服务器现在在使用 TLS 1.2 时宣称支持 SHA-512 签名。服务器已经支持这些签名,但有些客户端除非明确宣称,否则不会选择它们。
crypto/x509
Certificate.Verify
现在会强制执行证书中所有名称的名称约束,而不仅仅是客户端查询的单个名称。扩展密钥用法限制也同样一次性检查。因此,证书验证后,现在可以完全信任它。不再需要为每个附加名称或密钥用法重新验证证书。
已解析的证书现在还使用新的 Certificate
字段 URIs
、PermittedIPRanges
、ExcludedIPRanges
、PermittedEmailAddresses
、ExcludedEmailAddresses
、PermittedURIDomains
和 ExcludedURIDomains
报告 URI 名称以及 IP、电子邮件和 URI 约束。具有这些字段无效值的证书现在将被拒绝。
新的 MarshalPKCS1PublicKey
和 ParsePKCS1PublicKey
函数将 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_386
、R_AARCH64
、R_ARM
、R_PPC64
和 R_X86_64
之间添加了 348 个新的重定位常量。
debug/macho
Go 1.10 添加了对从 Mach-O 段读取重定位的支持,使用 Section
结构体的新 Relocs
字段以及新的 Reloc
、RelocTypeARM
、RelocTypeARM64
、RelocTypeGeneric
和 RelocTypeX86_64
类型以及相关常量。
Go 1.10 还添加了对 LC_RPATH
加载命令的支持,由类型 RpathCmd
和 Rpath
表示,以及用于头部中各种标志位的新命名常量。
encoding/asn1
Marshal
现在正确地将包含星号的字符串编码为 UTF8String 类型,而不是 PrintableString,除非该字符串在带有强制使用 PrintableString 标签的结构体字段中。Marshal
现在也遵守包含 application
指令的结构体标签。
新的 MarshalWithParams
函数会将其参数封送,就像额外的参数是其关联的结构体字段标签一样。
Unmarshal
现在遵守使用 explicit
和 tag
指令的结构体字段标签。
Marshal
和 Unmarshal
现在都支持一个新的结构体字段标签 numeric
,表示 ASN.1 NumericString。
encoding/csv
Reader
现在不允许使用无意义的 Comma
和 Comment
设置,例如 NUL、回车、换行、无效符文和 Unicode 替换字符,或者将 Comma
和 Comment
设置为彼此相等。
在 CSV 记录跨越多行输入且出现语法错误的情况下,Reader
现在会在 ParseError
的新 StartLine
字段中报告记录开始的行号。
encoding/hex
新的函数 NewEncoder
和 NewDecoder
提供流式十六进制转换,类似于 encoding/base32 和 encoding/base64 中已有的等效函数。
当 Decode
和 DecodeString
函数遇到格式错误的输入时,它们现在会返回已转换的字节数以及错误。以前,它们总是返回 0 与任何错误。
encoding/json
Decoder
添加了一个新方法 DisallowUnknownFields
,它会导致在解码时将带有未知 JSON 字段的输入报告为解码错误。(默认行为始终是丢弃未知字段。)
由于修复了一个反射 bug,Unmarshal
不再能够解码到嵌入式指向未导出结构体类型的指针中的字段,因为它无法初始化未导出的嵌入式指针以指向新存储。在这种情况下,Unmarshal
现在会返回一个错误。
encoding/pem
当遇到无法编码为 PEM 数据的块时,Encode
和 EncodeToMemory
不再生成部分输出。
encoding/xml
新的函数 NewTokenDecoder
类似于 NewDecoder
,但它创建的解码器从 TokenReader
读取,而不是从 XML 格式的字节流读取。这旨在使客户端库能够构建 XML 流转换器。
flag
默认的 Usage
函数现在将其输出的第一行打印到 CommandLine.Output()
,而不是假设 os.Stderr
,以便使用 CommandLine.SetOutput
的客户端可以正确重定向用法消息。
PrintDefaults
现在会在标志用法字符串中的换行符后添加适当的缩进,以便多行用法字符串显示得更好。
FlagSet
添加了新方法 ErrorHandling
、Name
和 Output
,以检索传递给 NewFlagSet
和 FlagSet.SetOutput
的设置。
go/doc
为了支持上面描述的文档更改,返回 T
、*T
、**T
等切片的函数现在在 T
的 Type
的 Funcs
列表中报告,而不是在 Package
的 Funcs
列表中。
go/importer
For
函数现在接受非 nil 的查找参数。
go/printer
上面gofmt 部分讨论的 Go 源代码默认格式的更改已在 go/printer 包中实现,并且也影响了更高级别的 go/format 包的输出。
hash
现在鼓励 Hash
接口的实现也实现 encoding.BinaryMarshaler
和 encoding.BinaryUnmarshaler
,以允许保存和重新创建其内部状态,并且标准库中的所有实现(hash/crc32、crypto/sha256 等)现在都实现了这些接口。
html/template
新的 Srcset
内容类型允许正确处理 img
标签的 srcset
属性中的值。
math/big
Int
现在支持在其 SetString
和 Text
方法中进行 2 到 62 进制的转换。(以前它只允许 2 到 36 进制。)常量 MaxBase
的值已更新。
Int
添加了一个新的 CmpAbs
方法,该方法类似于 Cmp
,但只比较其参数的绝对值(不比较符号)。
math/cmplx
Asin
、Asinh
、Atan
和 Sqrt
中的分支切割和其他边界情况已更正,以符合 C99 标准中使用的定义。
math/rand
新的 Shuffle
函数和相应的 Rand.Shuffle
方法打乱输入序列。
math
新的函数 Round
和 RoundToEven
将其参数四舍五入到最接近的浮点整数;Round
将半整数四舍五入到其较大的整数邻居(远离零),而 RoundToEven
将半整数四舍五入到其偶数整数邻居。
新的函数 Erfinv
和 Erfcinv
计算逆误差函数和逆补误差函数。
mime/multipart
Reader
现在接受文件名属性为空的部分。
mime
ParseMediaType
现在会丢弃无效的属性值;以前它会将这些值作为空字符串返回。
net
此包中的 Conn
和 Listener
实现现在保证当 Close
返回时,底层文件描述符已关闭。(在早期版本中,如果 Close
停止了其他 goroutine 中的挂起 I/O,则文件描述符的关闭可能会在 Close
返回后不久在这些 goroutine 中的一个中发生。)
TCPListener
和 UnixListener
现在实现 syscall.Conn
,以允许使用 syscall.RawConn.Control
在底层文件描述符上设置选项。
由 Pipe
返回的 Conn
实现现在支持设置读写截止时间。
IPConn.ReadMsgIP
、IPConn.WriteMsgIP
、UDPConn.ReadMsgUDP
和 UDPConn.WriteMsgUDP
方法现在已在 Windows 上实现。
net/http
在客户端,HTTP 代理(最常见的是通过 ProxyFromEnvironment
配置的)现在可以指定为 https://
URL,这意味着客户端通过 HTTPS 连接到代理,然后发出标准的代理 HTTP 请求。(以前,HTTP 代理 URL 必须以 http://
或 socks5://
开头。)
在服务器端,FileServer
及其单文件等效项 ServeFile
现在将 If-Range
检查应用于 HEAD
请求。FileServer
现在还将目录读取失败报告给 Server
的 ErrorLog
。内容服务处理程序在服务零长度内容时也会省略 Content-Type
头部。
ResponseWriter
的 WriteHeader
方法现在在传递无效(非 3 位数)状态码时会发生 panic。
当 Handler
不写入任何输出时,Server
将不再添加隐式 Content-Type。
Redirect
现在在写入 HTTP 响应之前设置 Content-Type
头部。
net/mail
ParseAddress
和 ParseAddressList
现在支持各种过时的地址格式。
net/smtp
Client
添加了一个新的 Noop
方法,用于测试服务器是否仍在响应。它现在还会防范在 Hello
和 Verify
方法的输入中可能出现的 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/page2
:path
之前的双斜杠被错误地重写为单个斜杠,而 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
添加了新方法 SetDeadline
、SetReadDeadline
和 SetWriteDeadline
,允许在底层文件描述符支持非阻塞 I/O 操作时设置 I/O 截止时间。这些方法的定义与 net.Conn
中的定义匹配。如果 I/O 方法因错过截止时间而失败,它将返回超时错误;新的 IsTimeout
函数报告错误是否表示超时。
同样与 net.Conn
匹配,File
的 Close
方法现在保证当 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.StartProcess
和 exec.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 个新表情符号。