Go 1.16发行说明

2021-02-17 18:23:14

最新的Go版本1.16版在Go 1.15之后六个月到货。它的大部分更改是在工具链,运行时和库的实现中进行的。与往常一样,该版本保留了Go 1兼容性的承诺。我们希望几乎所有Go程序都能像以前一样继续编译和运行。

Go 1.16通过GOOS = darwin,GOARCH = arm64在macOS(也称为Apple Silicon)上添加了对64位ARM架构的支持。与darwin / amd64端口一样,darwin / arm64端口也支持cgo,内部和外部链接,c-archive,c-shared和pie build模式以及竞争检测器。

iOS端口(以前称为darwin / arm64)已重命名为ios / arm64。 GOOS = ios表示darwin构建标签,就像GOOS = android表示linux构建标签一样。对于使用gomobile构建iOS应用的任何人,此更改都应该透明。

Go 1.16添加了一个ios / amd64端口,该端口针对在基于AMD64的macOS上运行的iOS模拟器。以前,这是通过带有ios build标签集的darwin / amd64非正式地支持的。另请参阅misc / ios / README,以获取有关如何为iOS和iOS模拟器构建程序的详细信息。

Go 1.16是将在macOS 10.12 Sierra上运行的最新版本。 Go 1.17需要macOS 10.13 High Sierra或更高版本。

Go现在在OpenBSD(openbsd / mips64端口)上支持MIPS64体系结构。此端口尚不支持cgo。

现在,在OpenBSD的64位x86和64位ARM体系结构(openbsd / amd64和openbsd / arm64端口)上,系统调用是通过libc进行的,而不是直接使用SYSCALL / SVC指令。这样可以确保与OpenBSD的未来版本具有向前兼容性。特别是,从OpenBSD 6.9起,需要通过libc对非静态Go二进制文件进行系统调用。

正如Go 1.15发行说明中所宣布的那样,Go 1.16放弃了对x87模式编译的支持(GO386 = 387)。现在可以使用软浮动模式(GO386 = softfloat)来支持非SSE2处理器。在非SSE2处理器上运行的用户应将GO386 = 387替换为GO386 = softfloat。

linux / riscv64端口现在支持cgo和-buildmode = pie。此版本还包括针对RISC-V的性能优化和代码生成改进。

默认情况下,启用模块感知模式,而不管当前工作目录或父目录中是否存在go.mod文件。更准确地说,GO111MODULE环境变量现在默认为on。要切换到以前的行为,请将GO111MODULE设置为auto。

默认情况下,像go build和go test这样的构建命令不再修改go.mod和go.sum。相反,如果需要添加或更新模块要求或校验和,它们将报告错误(就像使用了-mod = readonly标志一样)。可以使用go mod tidy或go get来调整模块要求和总和。

go install现在接受带有版本后缀的参数(例如,go install example.com/[email protected])。这将导致go install以模块感知模式构建和安装软件包,而忽略当前目录或任何父目录(如果有)中的go.mod文件。这对于在不影响主模块依赖性的情况下安装可执行文件很有用。

现在,建议使用带有或不带有版本后缀(如上所述)的go install来以模块模式构建和安装软件包。应该将go get与-d标志一起使用,以在不构建软件包的情况下调整当前模块的依赖性,并且不建议使用go get来构建和安装软件包。在将来的版本中,-d标志将始终启用。

现在可以在go.mod文件中使用调用指令来指示该模块的某些发行版本不应该被其他模块使用。在发现严重问题或无意发布该版本后,模块作者可以撤回该版本。

现在,go mod供应商和go mod tidy子命令接受-e标志,尽管它们在解决丢失的软件包时出错,但仍指示它们继续操作。

现在,go命令将忽略主模块中的exclude指令排除的模块版本要求。以前,go命令使用的下一个版本要比排除的版本高,但是该版本会随着时间的推移而变化,从而导致生成的版本无法复制。

在模块模式下,go命令现在禁止导入包含非ASCII字符或带有前导点字符(。)的路径元素的路径。具有这些字符的模块路径已被禁止(请参阅模块路径和版本),因此此更改仅影响模块子目录中的路径。

go命令现在支持使用新的// go:embed指令将静态文件和文件树作为最终可执行文件的一部分包含在内。有关详细信息,请参见新的嵌入式程序包的文档。

使用go test时,在执行测试函数期间调用os.Exit(0)的测试现在将被视为失败。这将有助于捕获测试调用调用os.Exit(0)的代码从而停止运行所有将来测试的情况。如果TestMain函数调用os.Exit(0),则仍被认为是通过测试。

当-c或-i标志与未知标志一起使用时,go test报告错误。通常,未知标志会传递给测试,但是当使用-c或-i时,不会运行测试。

go get -insecure标志已弃用,并将在以后的版本中删除。该标志允许使用非安全方案(例如HTTP)从存储库中获取和解析自定义域,并且还绕过使用校验和数据库的模块和验证。要允许使用不安全的方案,请改用GOINSECURE环境变量。要绕过模块总和验证,请使用GOPRIVATE或GONOSUMDB。有关详细信息,请参见go帮助环境。

现在获取example.com/mod@patch要求主模块已经需要一些版本的example.com/mod。 (但是,go get -u = patch仍会修补新添加的依赖项。)

GOVCS是一个新的环境变量,它限制go命令可以用来下载源代码的版本控制工具。使用通常在受信任的,经过身份验证的环境中使用的工具,可以缓解安全问题。默认情况下,可以使用git和hg从任何存储库下载代码。 svn,bzr和化石只能用于从存储库中下载代码,这些存储库中的模块路径或包路径与GOPRIVATE环境变量中的模式匹配。有关详细信息,请参见go help vcs。

现在,当主模块的go.mod文件声明go 1.16或更高版本时,所有程序包模式现在仅匹配那些由主模块中的程序包或测试以可迁移方式导入的程序包。 (不再包含通过测试来导入由主模块导入的软件包的软件包。)这与从Go 1.11开始由go mod供应商保留的软件包相同。

当在调用工具链程序(例如compile或asm)时指定-toolexec build标志以使用程序时,环境变量TOOLEXEC_IMPORTPATH现在设置为正在构建的包的导入路径。

现在已弃用了go build,go install和go test接受的-i标志。 -i标志指示go命令安装由命令行上命名的软件包导入的软件包。由于构建缓存是在Go 1.10中引入的,因此-i标志不再对构建时间产生重大影响,并且在无法写入安装目录时会导致错误。

当指定-export标志时,BuildID字段现在设置为已编译软件包的构建ID。这等效于在转到列表-exported -f {{.Export}}上运行go工具buildid,但是没有额外的步骤。

-overlay标志指定一个JSON配置文件,其中包含一组文件路径替换。 -overlay标志可以与所有构建命令和go mod子命令一起使用。它主要供gopls之类的编辑器工具使用,以了解未保存的更改对源文件的影响。配置文件将实际文件路径映射到替换文件路径,并且go命令及其构建将运行,就像实际文件路径与替换文件路径给出的内容一起存在,或者如果替换文件路径为空的。

cgo工具将不再尝试将C结构位域转换为Go结构域,即使它们的大小可以用Go表示。 C位字段在内存中出现的顺序取决于实现,因此在某些情况下,cgo工具生成的结果在默默上是不正确的。

现在,vet工具会警告有关test.T方法的无效调用,该方法是在测试过程中创建的goroutine中致命的。这也会警告在test.T测试或testing.B基准测试上调用Fatalf,FailNow和Skip {,f,Now}方法。

调用这些方法将停止执行所创建的goroutine,而不是Test *或Benchmark *函数。因此,必须由运行测试或基准测试功能的goroutine调用它们。例如:

func TestFoo(t * testing.T){go func(){if condition(){t.Fatal(" oops")// //退出内部函数而不是TestFoo。 } ...}()}

应该重写从已创建的goroutine中调用t.Fatal(或类似方法)的代码,以使用t.Error表示测试失败,并使用替代方法(例如使用return语句)尽早退出goroutine。前面的示例可以重写为:

func TestFoo(t * testing.T){go func(){if condition(){t.Error(" oops")return} ...}()}

vet工具现在警告有关amd64汇编,该汇编破坏了BP寄存器(帧指针)而不保存和恢复它,这与调用约定相反。必须将不保留BP寄存器的代码修改为完全不使用BP或通过保存和恢复BP来保留BP。保留BP的一种简单方法是将帧大小设置为非零值,这会导致生成的序言和结语为您保留BP寄存器。有关示例修复程序,请参见CL 248260。

兽医工具现在警告有关错误地将非指针或nil参数传递给asn1.Unmarshal。就像对encoding / json.Unmarshal和encoding / xml.Unmarshal的现有检查一样。

新的运行时/指标包引入了一个稳定的接口,用于从Go运行时中读取实现定义的指标。它取代了现有功能,如runtime.ReadMemStats和debug.GCStats,并且更加通用和高效。有关更多详细信息,请参见软件包文档。

现在将GODEBUG环境变量设置为inittrace = 1会导致运行时为每个程序包init发出一行标准错误,总结其执行时间和内存分配。此跟踪可用于查找Go启动性能的瓶颈或回归。 GODEBUG文档描述了格式。

在Linux上,运行时现在默认为迅速(使用MADV_DONTNEED)向操作系统释放内存,而不是在操作系统处于内存压力下(使用MADV_FREE)懒惰地释放内存。这意味着像RSS这样的进程级内存统计信息将更准确地反映Go进程正在使用的物理内存量。当前正在使用GODEBUG = madvdontneed = 1来改善内存监视行为的系统不再需要设置此环境变量。

Go 1.16修复了竞速检测器和Go内存模型之间的差异。现在,竞赛检测器可以更精确地遵循内存模型的通道同步规则。结果,检测器现在可以报告先前错过的比赛。

编译器现在可以内联具有未标记的循环,方法值和类型开关的函数。内联还可以在可能进行内联的情况下检测更多的间接调用。

此版本包括对Go链接程序的其他改进,减少了链接程序资源的使用(时间和内存),并提高了代码的健壮性/可维护性。这些更改构成了两个版本的项目的后半部分,以使Go链接器现代化。

1.16版中的链接器更改将1.15版改进扩展到所有受支持的体系结构/ OS组合(1.15版性能改进主要集中在基于ELF的OS和amd64体系结构上)。对于一组代表性的大型Go程序,Linux / amd64的链接速度比1.15快20-25%,平均所需内存减少5-15%,其他架构和OS的改进也更大。由于更严格的符号修剪,大多数二进制文件也较小。

在Windows上,build -buildmode = c-shared现在默认情况下会生成Windows ASLR DLL。可以使用--ldflags = -aslr = false禁用ASLR。

新的embed包可使用新的// go:embed指令访问编译过程中嵌入的文件。

新的io / fs包定义了fs.FS接口,它是文件只读树的抽象。标准库软件包已进行了适当调整,以利用该接口。

在接口的生产者端,新的embed.FS类型实现了fs.FS,而zip.Reader也是如此。新的os.DirFS函数提供了由操作系统文件树支持的fs.FS的实现。

在使用者方面,新的http.FS函数将fs.FS转换为http.FileSystem。另外,html / template和text / template程序包的ParseFS函数和方法从fs.FS读取模板。

对于实现fs.FS的测试代码,新的testing / fstest软件包提供了TestFS功能,用于检查并报告常见错误。它还提供了一个简单的内存文件系统实现MapFS,可用于测试接受fs.FS实现的代码。

io / ioutil程序包的定义很模糊,很难理解。软件包提供的所有功能已移至其他软件包。 io / ioutil包仍然存在,并且将像以前一样继续工作,但是我们鼓励新代码使用io和os包中的新定义。这是io / ioutil导出的名称的新位置的列表:

与往常一样,对库的各种微小更改和更新都遵循了Go 1的兼容性承诺。

如果对哈希生成函数的单独调用无法返回新值,则New现在会感到恐慌。以前,行为是不确定的,有时会生成无效的输出。

现在可以使用新的net.ErrClosed错误来检测关闭或关闭的TLS连接上的I / O操作。典型的用法是error.Is(err,net.ErrClosed)。

现在,在Conn.Close中设置默认的写截止时间,然后发送" close通知"警报,以防止无限期阻塞。

现在,如果服务器选择不在客户端发布的列表中的ALPN协议,则客户端将返回握手错误。

如果客户端或服务器不支持AES硬件,则服务器现在将更喜欢其他可用的AEAD密码套件(例如ChaCha20Poly1305),而不是AES-GCM密码套件,除非同时设置了Config.PreferServerCipherSuites和Config.CipherSuites。如果该客户端未发出对AES-GCM密码套件的优先选择,则假定该客户端不具有AES硬件支持。

GO 1.17中将删除GODEBUG = x509ignoreCN = 0标志。当不存在使用者备用名称时,它启用了将X.509证书上的CommonName字段视为主机名的传统行为。

现在,ParseCertificate和CreateCertificate对DNSNames,EmailAddresses和URI字段实施字符串编码限制。这些字段只能包含字符在ASCII范围内的字符串。

现在,CreateCertificate使用签名者的公钥来验证生成的证书的签名。如果签名无效,则返回错误,而不是格式错误的证书。

不再支持DSA签名验证。请注意,从未支持过DSA签名生成。请参阅问题#40337。

在Windows上,Certificate.Verify现在将返回由平台证书验证者构建的所有证书链,而不仅仅是排名最高的链。

在Unix系统上,crypto / x509软件包现在在存储系统证书池副本方面更加有效。仅使用少量根的程序将使用大约少半兆的内存。

现在,当参数不是指针或为nil时,Unmarshal和UnmarshalWithParams返回错误而不是惊慌。此更改与其他编码包(例如encoding / json)的行为匹配。

Marshal,Unmarshal和相关功能可以理解的json结构字段标签现在允许Go结构字段的JSON对象名称中包含分号字符。

编码器始终注意避免使用以xml开头的名称空间前缀,XML规范保留了该名称空间。现在,更严格地遵循规范,该检查是不区分大小写的,因此也避免了以XML,XmL等开头的前缀。

新的Func函数允许注册通过调用函数实现的标志,作为实现Value接口的轻巧替代方案。

Package结构具有新字段,用于报告有关// go:embed指令的信息:EmbedPatterns,EmbedPatternPos,TestEmbedPatterns,TestEmbedPatternPos,XTestEmbedPatterns,XTestEmbedPatternPos。

包字段IgnoredGoFiles将不再包含以" _"开头的文件。或"。&#34 ;,因为这些文件始终被忽略。 IgnoredGoFiles用于由于构建约束而被忽略的文件。

由于构建约束,新的Package字段IgnoredOtherFiles列出了非Go文件的列表。

新的go / build / constraint包解析了构建约束线,包括原始// + build语法和// go:build语法,这些语法将在Go 1.17中引入。存在此软件包的目的是使使用Go 1.16构建的工具能够处理Go 1.17源代码。有关构建约束语法以及计划过渡到// go:build语法的详细信息,请参见https://golang.org/design/draft-gobuild。请注意,Go 1.16不支持// go:build行,并且尚不应将其引入Go程序中。

新的template.ParseFS函数和template.Template.ParseFS方法类似于template.ParseGlob和template.Template.ParseGlob,但是从fs.FS中读取模板。

软件包现在定义了Discard,NopCloser和ReadAll,而不是在io / ioutil软件包中使用相同的名称。

现在,在登录到自定义Unix域套接字时,Writer使用本地消息格式(省略主机名并使用较短的时间戳),与已用于默认日志套接字的格式匹配。

当传递最大int64值作为限制时,Reader的ReadForm方法不再拒绝表单数据。

现在,可以使用新的ErrClosed错误来检测封闭的网络连接上的I / O情况,或者在任何I / O完成之前关闭的网络连接上的I / O情况。典型的用法是error.Is(err,net.ErrClosed)。在较早的版本中,可靠地检测到这种情况的唯一方法是将Error方法返回的字符串与"使用封闭网络连接"进行匹配。

在以前的Go发行版中,由/ proc / sys / net / core / somaxconn设置的Linux系统上的默认TCP侦听器积压大小最大为65535。在Linux内核版本4.1和更高版本上,现在最大为4294967295。

在Linux上,当/etc/nsswitch.conf丢失时,在检查/ etc / hosts之前,主机名查找不再使用DNS。这在基于Musl的系统上很常见,并使Go程序与那些系统上C程序的行为相匹配。

在net / http程序包中,StripPrefix的行为已更改,以从请求URL的RawPath字段中除去其Path字段之外的前缀。 在以前的版本中,仅修剪了“路径”字段,因此,如果请求URL中包含 ......