马特·皮尔林和亚历克斯·拉科齐
2021 年 8 月 16 日
今天,Go 团队很高兴发布 Go 1.17,您可以通过访问 下载页面获得。
编译器改进
此版本为编译器带来了额外的改进,即传递函数参数和结果的 新方法。这一变化表明,Go 程序的性能提高了约 5%,amd64 平台的二进制文件大小减少了约 2%。未来版本将支持更多平台。
Go 1.17 实现了一种使用寄存器而不是堆栈传递函数参数和结果的新方法。一组具有代表性的 Go 包和程序的基准测试显示,性能提高了约 5%,二进制大小通常减少了约 2%。这是目前在Linux,MacOS和Windows中启用的64位x86架构(的linux/amd64, darwin/amd64和windows/amd64端口)。
此更改不会影响任何安全 Go 代码的功能,并且不会影响大多数汇编代码。它可能会影响unsafe.Pointer 访问函数参数时违反规则的代码,或者取决于涉及比较函数代码指针的未记录行为。为了保持与现有汇编函数的兼容性,编译器生成了在新的基于寄存器的调用约定和以前的基于堆栈的调用约定之间进行转换的适配器函数。这些适配器通常对用户不可见,除了在汇编代码中获取 Go 函数的地址或在 Go 代码中使用reflect.ValueOf(fn).Pointer() 或获取汇编函数的地址之外unsafe.Pointer现在将返回适配器的地址。依赖于这些代码指针值的代码可能不再按预期运行。在两种情况下,适配器也可能导致非常小的性能开销:通过func值从 Go 间接调用汇编函数,以及从汇编调用 Go 函数。
运行时堆栈跟踪的格式(在发生未捕获的恐慌时或runtime.Stack调用时打印)得到改进。以前,函数参数根据内存布局打印为十六进制字。现在源代码中的每个参数都单独打印,用逗号分隔。聚合类型(结构、数组、字符串、切片、接口和复杂)参数由花括号分隔。需要注意的是,仅存在于寄存器中而不存储到内存中的参数的值可能不准确。不再打印函数返回值(通常不准确)。
现在可以内联包含闭包的函数。此更改的一个影响是,带有闭包的函数可能会为函数内联的每个位置生成一个不同的闭包代码指针。Go 函数值不能直接比较,但此更改可能会揭示使用reflect 或unsafe.Pointer绕过此语言限制并通过代码指针比较函数的代码中的错误。
windows ARM
Go 1.17 还增加了 对 Windows 上 64 位 ARM 架构的支持,让 gophers 在更多设备上本地运行 Go。
go module
我们还在此版本中引入了修剪后的模块图。go 1.17在其go.mod文件中指定或更高的模块将使其模块图仅包含其他 Go 1.17 模块的直接依赖项,而不是它们的完整传递依赖项。这应该有助于避免go.mod为其他不相关的依赖项下载或读取文件的需要——节省日常开发的时间。
Go 1.17对语言进行了三个小改动。前两个是unsafe包中的新函数,使程序更容易遵守unsafe.Pointer规则:unsafe.Add允许 更安全的指针算术,同时unsafe.Slice允许 更安全地将指针转换为切片。第三个变化是语言类型转换规则的扩展,允许从切片到数组指针的转换 ,前提是切片在运行时至少与数组一样大。
最后还有很多其他改进和错误修复,包括对crypto/x509 的验证改进,以及对URL 查询解析的更改 。有关更改的完整列表以及有关上述改进的更多信息,请参阅 完整的发行说明。
感谢所有通过编写代码、提交错误、分享反馈以及测试 Beta 版和候选发布版而为此版本做出贡献的人。您的努力有助于确保 Go 1.17 尽可能稳定。与往常一样,如果您发现任何问题,请 提出问题。
我们希望您喜欢新版本!