go 1.16简介

最新的Go版本1.16在Go 1.15 6个月后发布。它的大多数更改都是在工具链、运行时和库的实现中进行的。和往常一样,这个版本保持了Go 1对兼容性的承诺。我们希望几乎所有的Go程序都能像以前一样继续编译和运行

语言变更

语言没有变化

工具类

go test

当使用 os.Exit(0) 会被认定为测试失败


Runtime

调整切片扩容策略

Go1.16 以前的 slice 的扩容条件是 len,在最新的代码中,已经改为了以 cap 属性作为基准:

  1. // src/runtime/slice.go
  2. if cap > doublecap {
  3. newcap = cap
  4. } else {
  5. // 这是以前的代码:if old.len < 1024 {
  6. // 下面是 Go1.16rc1 的代码
  7. if old.cap < 1024 {
  8. newcap = doublecap
  9. }

以官方的 test case 为例:

  1. func main() {
  2. const N = 1024
  3. var a [N]int
  4. x := cap(append(a[:N-1:N], 9, 9))
  5. y := cap(append(a[:N:N], 9))
  6. println(cap(x), cap(y))
  7. }

在 Go1.16 以前输出 2048, 1280。在 Go1.16 及以后输出 1280, 1280,保证了两种的一致

核心库

废弃 io/ioutil

Go 官方认为 io/ioutil 这个包的定义不明确且难以理解。所以 Russ Cox 在 2020.10.17 提出了废弃 io/ioutil 的提案。
大致变更如下:

  • Discard => io.Discard
  • NopCloser => io.NopCloser
  • ReadAll => io.ReadAll
  • ReadDir => os.ReadDir
  • ReadFile => os.ReadFile
  • TempDir => os.MkdirTemp
  • TempFile => os.CreateTemp
  • WriteFile => os.WriteFile

与此同时大家也不需要担心存在破坏性变更,因为有 Go1 兼容性的保证,在 Go1 中 io/ioutil 还会存在,只变更内部的方法调用:

  1. func ReadAll(r io.Reader) ([]byte, error) {
  2. return io.ReadAll(r)
  3. }
  4. func ReadFile(filename string) ([]byte, error) {
  5. return os.ReadFile(filename)
  6. }

支持静态资源嵌入

  1. import _ "embed"
  2. //go:embed hello.txt
  3. var s string
  4. print(s)

新增 io/fs 的支持

新增了标准库 io/fs,正式将文件系统相关的基础接口抽象到了该标准库中。
以前的话大多是在 os 标准库中,这一步抽离更进一步的抽象了文件树的接口。在后续的版本中,大家可以优先考虑使用 io/fs 标准库。