文章目录
- 1.Go 1.19 简介
- 2.语言的变化
- 3.内存模型
- 4.端口
- 4.1 LoongArch 64-bit
- 4.2 RISC-V
- 5.工具
- 5.1 文档评论
- 5.2 新的 unix 构建约束
- 5.3 Go 命令
- 5.3 Vet
- 6.Runtime
- 7.编译器
- 8.汇编器
- 9.链接器
- 10 核心库
- 10.1 新的原子类型
- 10.2 PATH 查找
- 10.3 库的小改动
- archive/zip
- crypto/elliptic
- crypto/rand
- crypto/tls
- crypto/x509
- crypto/x509/pkix
- debug/elf
- debug/pe
- encoding/binary
- encoding/csv
- 参考文献
美国时间 2022 年 8 月 2 日,Go 团队官宣 Go 1.19 正式发布。下面让我们一起了解下 Go 1.19 为我们带来的新特性吧。
本文主要翻译自 Go 1.19 Release Notes - The Go Programming Language。
1.Go 1.19 简介
最新的 Go 版本 1.19 比 Go 1.18 晚了五个月。它的大部分更改都在工具链、运行时和库中。与往常一样,该版本保持了 Go 1 的兼容性承诺。我们希望几乎所有 Go 程序都能像以前一样继续编译和运行。
2.语言的变化
语言只有一个很小的变化,对方法声明中类型参数的范围进行了很小的修正。现有程序不受影响。
3.内存模型
Go 内存模型已经过修改,以使 Go 与 C、C 、Java、JavaScript、Rust 和 Swift 使用的内存模型保持一致 。Go 只提供顺序一致的原子,而不是在其他语言中发现的任何更宽松的形式。随着内存模型的更新,Go 1.19在包中引入了新的类型sync/atomic ,使原子值的使用变得更容易,例如 atomic.Int64 和 atomic.Pointer[T]。
4.端口
4.1 LoongArch 64-bit
Go 1.19 在 Linux (GOOS=linux, GOARCH=loong64)上增加了对龙芯 64 位架构 LoongArch 的支持。实现的 ABI 是 LP64D。支持的最低内核版本为 5.19。
请注意,大多数现有的 LoongArch 商业 Linux 发行版都带有较旧的内核,具有历史上不兼容的系统调用 ABI。即使静态链接,编译后的二进制文件也无法在这些系统上运行。此类不受支持的系统上的用户仅限于分发提供的 Go 包。
4.2 RISC-V
该 riscv64 端口现在支持使用寄存器传递函数参数和结果。基准测试表明,在 riscv64 上的典型性能提高了10%或更多。
5.工具
5.1 文档评论
Go 1.19 在文档注释中添加了对链接、列表和更清晰标题的支持。作为此更改的一部分,gofmt 现在重新格式化文档注释以使其呈现的含义更清晰。请参阅 “Go Doc Comments” 以获取语法详细信息和现在 gofmt 突出显示的常见错误的描述。作为此更改的另一部分,新包 go/doc/comment 提供了对文档注释的解析和重新格式化,并支持将它们呈现为 HTML、Markdown 和文本。
5.2 新的 unix 构建约束
unix 现在可以按//go:build
行识别构建约束。如果目标操作系统(也称为 GOOS)是 Unix 或类 Unix 系统,则满足约束。对于 1.19 版本,如果 GOOS 是 aix, android, darwin, dragonfly, freebsd, hurd, illumos, ios, linux, netbsd, openbsd 或 solaris 中的一个则满足 。在未来的版本中,该 unix 约束可能与其他新支持的操作系统相匹配。
5.3 Go 命令
-trimpath 标志(如果设置)现在可以通过 go build 标记到 Go 二进制文件中的构建设置中 ,并且可以使用 go version -m 或检查 debug.ReadBuildInfo。
go generate 现在在生成器的环境中显式设置环境变量 GOROOT,这样即使使用 -trimpath 构建,生成器也可以找到正确的 GOROOT。
go test 和 go generate 现在将 GOROOT/bin 放在用于子进程的 PATH 的开头,因此执行 go 命令的测试和生成器会将其解析为相同的 GOROOT。
go env 报告环境变量 CGO_CFLAGS、CGO_CPPFLAGS、CGO_CXXFLAGS、CGO_FFLAGS、CGO_LDFLAGS 和 GOGCCFLAGS 时,现在使用引号括起包含空格的条目。
go list -json 现在接受以逗号分隔的 JSON 字段列表来填充。 如果指定了列表,则 JSON 输出将仅包含那些字段,并且 go list 可能会避免计算未包含的字段。 在某些情况下,这可能会抑制某些错误。
go 命令现在缓存了加载某些模块所需的信息,这应该会加快某些 go list 调用的速度。
5.3 Vet
当调用 errors.As 第二个参数使用 *error 类型的参数时,这是一个常见错误,vet 检查器 “errorsas” 现在会报告错误。
6.Runtime
运行时现在包括对软内存限制的支持。 此内存限制包括 Go 堆和运行时管理的所有其他内存,不包括外部内存源,例如二进制文件本身的映射、其他语言管理的内存以及操作系统代表 Go 程序持有的内存。此限制可以通过 runtime/debug.SetMemoryLimit 或等效的GOMEMLIMIT 环境变量来管理。该限制与 runtime/debug.SetGCPercent / GOGC 结合使用,即使 GOGC=off 也会生效,允许 Go 程序始终最大限度地利用其内存限制,在某些情况下提高了资源效率。有关更详细地解释软内存限制以及各种常见用例和场景的详细指南,请参阅 GC 指南。请注意,由于外部延迟因素(例如 OS 调度),较小的内存限制(大约数十兆字节或更小)不太可能会生效。有关详细信息,请参阅 issue 52433。更大的内存限制,大约数百兆字节或更多,是稳定的和生产就绪的。
为了在程序的活动堆大小接近软内存限制时限制 GC 抖动的影响,Go 运行时还尝试将总 GC CPU 利用率限制为 50%,不包括空闲时间,选择使用更多内存而不是阻止应用程序执行。在实践中,我们希望此限制仅在特殊情况下发挥作用,并且新的运行时指标 /gc/limiter/last-enabled:gc-cycle 会报告最后一次发生的时间。
当应用程序空闲到足以强制执行周期性 GC 循环时,运行时现在在空闲操作系统线程上调度更少的 GC worker goroutines。
运行时现在将根据 goroutine 的历史平均堆栈使用情况分配初始 goroutine 堆栈。这避免了在平均情况下需要的一些早期堆栈增长和复制,但在低于平均水平的 goroutines 上最多会有 2 倍的空间浪费。
在 Unix 操作系统上,导入包 os 的 Go 程序现在会自动将打开文件限制 ( RLIMIT_NOFILE) 增加到允许的最大值;也就是说,他们更改软限制以匹配硬限制。这更正了在某些系统上人为设置的低的上限,以便与使用 select 系统调用的非常旧的 C 程序兼容 。Go 程序并没有受到这种限制的帮助,相反,即使是简单的程序 gofmt ,例如在此类系统上并行处理许多文件时,也经常会用完文件描述符。这一变化的一个影响是,在子进程中执行非常旧的 C 程序的 Go 程序可能会以过高的限制运行这些程序。这可以通过在调用 Go 程序之前设置硬限制来纠正。
除非 GOTRACEBACK=system 或 crash,否则不可恢复的致命错误(例如并发映射写入或解锁未锁定的互斥锁)现在打印更简单的回溯,不包括运行时元数据(相当于致命恐慌)。无论 GOTRACEBACK 的值如何,运行时内部的致命错误回溯始终包含完整的元数据。
在 ARM64 上添加了对调试器注入函数调用的支持,使用户能够在使用经过更新以利用此功能的调试器时,在交互式调试会话中从其二进制文件调用函数。
Go 1.18 中添加的地址清理器现在可以更精确地处理函数参数和全局变量。
7.编译器
编译器现在使用跳转表来实现大整数和字符串 switch 语句。 switch 语句的性能改进各不相同,但可以快 20% 左右。 (仅限 GOARCH=amd64 和 GOARCH=arm64)
Go 编译器现在需要 -p=importpath 标志来构建可链接的目标文件。这已经由 go 命令和 Bazel 提供。任何其他直接调用 Go 编译器的构建系统都需要确保它们也传递了这个标志。
Go编译器不再接受 -importmap 标志。直接调用Go编译器的构建系统必须改用 -importcfg 标志。
8.汇编器
与编译器一样,汇编器现在需要该 -p=importpath 标志来构建可链接的目标文件。这已经由 go 命令提供。任何其他直接调用 Go 汇编器的构建系统都需要确保它们也传递了这个标志。
9.链接器
在 ELF 平台上,链接器现在以标准 gABI 格式 ( SHF_COMPRESSED) 发出压缩的 DWARF 部分,而不是传统 .zdebug 格式。
10 核心库
10.1 新的原子类型
该 sync/atomic 包定义了新的原子类型 Bool, Int32, Int64, Uint32, Uint64, Uintptr 和 Pointer。这些类型隐藏了底层值,因此所有访问都被迫使用原子 API。Pointer 还避免了在调用处转换为 unsafe.Pointer 的需要。 Int64 和 Uint64 在结构和分配的数据中自动对齐到 64 位边界,即使在 32 位系统上也是如此。
10.2 PATH 查找
Command 和 LookPath 不再允许相对于当前目录找到 PATH 搜索的结果。这消除了一个常见的安全问题来源, 但也可能破坏现有的程序,这些程序依赖于在当前目录使用exec.Command("prog")
中运行名为 prog(或在 Windows 上叫 prog.exe)的二进制文件。有关如何最好地更新此类程序的信息,请参阅 os/exec 包文档。
在 Windows 上,Command 和 LookPath 现在尊重 NoDefaultCurrentDirectoryInExePath 环境变量,从而可以禁用 Windows 系统上 PATH 查找时 “.” 的隐式默认搜索。
10.3 库的小改动
与往常一样,在考虑到 Go 1 的兼容性承诺的情况下,对库进行了各种细微的更改和更新。 还有各种性能提升,这里就不一一列举了。
archive/zip
crypto/elliptic
crypto/rand
crypto/tls
crypto/x509
crypto/x509/pkix
TODO
debug/elf
debug/pe
encoding/binary
encoding/csv
参考文献
Go 1.19 Release Notes - The Go Programming Language