背景

Go官网团队在Go 1.18 Beta 1版本的规范库里因为泛型设计而引入了contraints包。

constraints包里定义了SignedUnsigned, Integer, Float, ComplexOrdered共6个interface类型,能够用于泛型里的类型束缚(type constraint)。

比方咱们能够用constraints包写出如下泛型代码:

// test.gopackage mainimport (    "constraints"    "fmt")// return the min valuefunc 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 1float64 1string a

备注:如果对Go泛型和constraints包还不太理解的同学,能够翻看我之前写的一文读懂Go泛型设计和应用场景。

现状

Go官网团队的技术负责人Russ Cox在2022.01.25提议将constraints包从Go规范库里移除,放到x/exp我的项目下。Russ Cox给出的理由如下:

There are still questions about the the constraints package. To start with, although many people are happy with the name, many are not. On top of that, it is unclear exactly which interfaces are important and should be present and which should be not. More generally, all the considerations that led us to move slices and maps to x/exp apply to constraints as well.

We left constraints behind in the standard library because we believed it was fundamental to using generics, but in practice that hasn't proven to be the case. In particular, most code uses any or comparable. If those are the only common constraints, maybe we don't need the package. Or if constraints.Ordered is the only other commonly used constraint, maybe that should be a predeclared identifier next to any and comparable. The ability to abbreviate simple constraints let us remove constraints.Chan, constraints.Map, and constraints.Slice, which probably would have been commonly used, but they're gone.

Unlike other interfaces like, say, context.Context, there is no compatibility issue with having a constraint interface defined in multiple packages. The problems that happen with duplicate interfaces involve other types built using that type, such as func(context.Context) vs func(othercontext.Context). But that cannot happen with constraints, because they can only appear as type parameters, and they are irrelevant to type equality for a particular substitution. So having x/exp/constraints and later having constraints does not cause any kind of migration problem at all, unlike what happened with context.

For all these reasons, it probably makes sense to move constraints to x/exp along with slices and maps for Go 1.18 and then revisit it in the Go 1.19 or maybe Go 1.20 cycle. (Realistically, we may not know much more for Go 1.19 than we do now.)

Discussed with @robpike, @griesemer, and @ianlancetaylor, who all agree.

该提议也同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名字太长,代码写起来比拟繁琐。
  • 大多数泛型的代码只用到了anycomparable这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语言高级、中级和高级教程。

公众号:coding进阶。关注公众号能够获取最新Go面试题和技术栈。

集体网站:Jincheng's Blog。

知乎:无忌。

References

  • https://github.com/golang/go/...
  • https://github.com/golang/go/...
  • https://pkg.go.dev/golang.org/x