Go 1.18将移除用于泛型的constraints包
背景
Go官方团队在Go 1.18 Beta 1版本的标准库里因为泛型设计而引入了contraints
包。
constraints
包里定义了Signed
,Unsigned
, Integer
, Float
, Complex
和Ordered
共6个interface类型,可以用于泛型里的类型约束(type constraint
)。
比如我们可以用constraints
包写出如下泛型代码:
// test.go
package main
import (
"constraints"
"fmt"
)
// return the min value
func min[T constraints.Ordered](a, b T) T {
fmt.Printf("%T ", a)
if a < b {
return a
}
return b
}
func main() {
minInt := min(1, 2)
fmt.Println(minInt)
minFloat := min(1.0, 2.0)
fmt.Println(minFloat)
minStr := min("a", "b")
fmt.Println(minStr)
}
函数min
是一个泛型函数,接收2个参数,返回其中的较小者。
类型参数T
的类型约束contraints.Ordered
的定义如下:
type Ordered interface {
Integer | Float | ~string
}
上面代码的执行结果为:
int 1
float64 1
string a
备注:如果对Go泛型和constraints
包还不太了解的同学,可以翻看我之前写的一文读懂Go泛型设计和使用场景。
现状
Go官方团队的技术负责人Russ Cox在2022.01.25提议将constraints
包从Go标准库里移除,放到x/exp
项目下。Russ Cox给出的理由如下:
该提议也同Go语言发明者Rob Pike, Robert Griesemer和Ian Lance Taylor做过讨论,得到了他们的同意。
其中Robert Griesemer和Ian Lance Taylor是Go泛型的设计者。
Russ Cox将这个提议在GitHub公布后,社区成员没有反对意见,因此在2022.02.03这个提议得到正式通过。
不过值得注意的是,2022.01.31发布的Go 1.18 Beta 2版本里还保留了constraints
包,不建议大家再去使用。
备注:
-
golang.org/x
下所有package的源码独立于Go源码的主干分支,也不在Go的二进制安装包里。如果需要使用golang.org/x
下的package,可以使用go get
来安装。 -
golang.org/x/exp
下的所有package都属于实验性质或者被废弃的package,不建议使用。
移除原因
支持泛型的Go 1.18 Beta 1版本发布以来,围绕着constraints
包的争议很多。
主要是以下因素,导致Russ Cox决定从Go标准库中移除constraints
包。
-
constraints
名字太长,代码写起来比较繁琐。 -
大多数泛型的代码只用到了
any
和comparable
这2个类型约束。constaints
包里只有constraints.Ordered
使用比较广泛,其它很少用。所以完全可以把Ordered
设计成和any
以及comparable
一样,都作为Go的预声明标识符,不用单独弄一个constraints
包。
总结
建议不要使用constraints
包,毕竟Go 1.18正式版本会去掉。
我写了2篇Go泛型入门的教程,欢迎大家参考
-
官方教程:Go泛型入门
-
一文读懂Go泛型设计和使用场景
好文推荐
-
Go Quiz: Google工程师的Go语言面试题
-
Go Quiz: 从Go面试题看slice的底层原理和注意事项
-
Go Quiz: 从Go面试题搞懂slice range遍历的坑
-
Go Quiz: 从Go面试题看channel的注意事项
-
Go Quiz: 从Go面试题看channel在select场景下的注意事项
-
Go Quiz: 从Go面试题看defer语义的底层原理和注意事项
-
Go Quiz: 从Go面试题看defer的注意事项第2篇
-
Go Quiz: 从Go面试题看defer的注意事项第3篇
-
Go Quiz: 从Go面试题看分号规则和switch的注意事项
开源地址
文章和示例代码开源在GitHub: Go语言初级、中级和高级教程。
个人网站:Jincheng's Blog。
知乎:无忌。
References
-
https://github.com/golang/go/issues/50792
-
https://github.com/golang/go/issues/50348
-
Sub-repositories - pkg.go.dev