Go1.14 重要新特性

Sep 22 2020 Golang

语言变更

内嵌接口方法集允许部分重叠

接口(interface)是方法集合,方法必须有唯一的非空名称。

之前的接口规范:一个接口 T 可以在方法集中使用接口 E,这里的 E 称之为 T 的内嵌接口,使得 E 中的所有公有和私有方法被添加到接口 T 中。

所以如下所示的 ReadWriteCloser 多个内嵌接口拥有同名 Close 方法是不允许的。

1
2
3
4
type ReadWriteCloser interface {
io.ReadCloser
io.WriteCloser
}

Go1.14 现在支持这种语法形式。

现在的接口规范:一个接口 T 可以在方法集中使用接口 E,这里的 E 称之为 T 的内嵌接口,T 的方法集是 T 中明确声明的方法以及T内嵌接口中方法的结合。这个方法集包含所有公有和私有方法,同名的方法必须拥有相同的函数签名。

以下为规范的示例:

显式重复多次声明相同的方法依然是不被允许的

1
2
3
4
type I interface {
m()
m() // 非法,m()已经显式声明
}

在 Go1.14 之前是允许内嵌多个空接口

1
2
type E interface {}
type I interface { E; E } // 总是合法

在 Go1.14 之后允许内嵌多个非空接口:

1
2
type E interface { m() }
type I interface { E; E } // 现已合法

如果不同的内嵌接口提供了同名方法,这些方法必须拥有相同的签名,否则就是非法的:

1
2
3
type E1 interface { m(x int) bool }
type E2 interface { m(x float32) bool }
type I interface { E1; E2 } // 非法:E1.m 和 E2.m 同名但是方法签名不同

Go命令变更

自动支持 vendor

如果当前 main 包基目录下包含一个 vendor 目录,并且 go.mod 显式说明仅支持 go1.14 或更高版本,那么所有的 go 命令都会显式的加入 -mod=vendor。另外一个新的命令行参数 -mod=mod,在没有 vendor 目录的时候会从模块本地缓存中读取。

当默认或者显式 -mod=vendor 的时候,go命令会校验 vendor/modules.txt 文件和 go.mod 声明的是一致的。

支持非TLS的私有仓库

在很久之前可以使用 go get -insecure 下载非 TLS 的私有仓库包,但是 go module 后不支持这种方式。

Go1.14现在支持声明环境变量的方式支持非安全连接的私有包,类似 GOPRIVATE 只需要定义逗号分割的 GOINSECURE 环境变量即可。

运行时变更

更快的 defer,而且是几乎零开销。现在 defer 可以在对性能至关重要的代码中使用,而无需担心新能开销。

Go 协程现在可以异步抢占,减少调度程序死锁或延迟垃圾回收的可能性。

timer 在调度中减少锁使用和上下文切换,性能提升明显。详情可以参考 《Go夜读 Go time.Timer 源码分析(Go1.14)》。

标准库变更

  1. 新包 hash/maphash 提供非密码学安全的哈希算法
  2. tls 移除 SSLv3 支持,TLS 1.3 默认开启