长达 12 年,Go 泛型才引入,是政治,还是技术问题?

19,548 阅读4分钟

大家好,我是煎鱼。

前两天 Go1.18 beta1 已经发布,距离正式发布 Go1.18 的生产可用还有 2 个月,也就是泛型即将正式面世。

最近正在收集泛型的一些资料,看到在 2015 年有人在 Hacker News 上的《Go 1.5 max procs default》吐槽 Go 不支持泛型是 “政治” 原因...

看了还是有些意义的,与现在的矛盾点基本一致,为此分享给大家。

网友吐槽

网友 @aikah 认为 Go 团队不太可能在语言中加入泛型,这显然是一个政治问题而不是技术问题。错误处理也是如此。

和许多人一样,该网友认为 Go 在极简主义和功能之间没有取得正确的平衡。反对泛型的人赞成用编译时类型检查(总是安全的)换取运行时类型断言(可能失败)。

他们拒绝承认这一事实。这就是他们反对泛型的论点,并将最终损害语言的任何潜在增长。他们基本上是在违背自己的利益。

官方回复

Russ Cox 做了正式的回复:很抱歉,但不是:泛型是一个技术问题,不是一个政治问题。

Go 团队并不反对泛型本身,只是反对做那些没有被很好理解或不能很好地与 Go 配合的事情。

这就是核心观点和矛盾点,也从 2009 年,延续到了现在。

会遇到的问题

Go 团队认为要将泛型的概念融入 Go,并与系统的其他部分很好地配合,必须解决一些深层次的技术问题,而我们并没有解决这些问题的办法。

关于这些问题,在几年前就在博客上写过一篇《The Generic Dilemma》:

即使克服了那一页上的问题,也有其他问题,接下来你会遇到的问题是:”如何让程序员以一种有用的、易于解释的方式省略类型注释“。

也就是如何更人性、更易于的表达泛型的类型参数。

泛型例子

举个例子,C++ 允许你写 make_pair(1, "foo"),而不是 make_pair<int, string>(1, "foo")

为了达到这种效果,推断注释背后的逻辑需要几页几页的规范,这并不是一个特别容易理解的编程模型,当事情出错时,编译器也不能轻易解释。

在这之后肯定还有更多的新问题在这里面。

和专家沟通

Go 团队和一些真正的 Java 泛型专家谈过,他们每个人都说了大致相同的话:要非常小心,它不像看起来那么容易,而且你会被你犯的所有错误困住。

作为一个 Java 示范,可以浏览一下《Java Generics FAQs - Frequently Asked Questions》的大部分内容:

看看过了多久你会开始思考 "这真的是最好的方法吗?"。

在泛型过程中会遇到许多问题,像是《How do I decrypt Enum<E extends Enum>》:

为此,Go 团队在泛型的推动上非常谨慎。

承认缺点

Go 团队说得很清楚,承认这个事实:没有泛型是有一定的缺点的

你要么使用 interface{} 而放弃编译时检查,要么写代码生成器而使你的构建过程复杂化。

现有语言中实现的泛型也有明确的缺点,而且今天不妥协有一个非常大的好处:它使明天采用更好的解决方案变得更加容易

总结

今天给大家分享了过去在国外社区针对 Go 泛型的各种争议和探讨,其实泛型的核心观点很明确:”Go 团队不反对泛型本身“。

一直没能把泛型做起来,也是因为顾虑很多,做泛型要和 Go 多个部分,要解决很多深层次的问题,还要解决类型参数可读性等问题。所以一直拖到了现在。

回到即将 2022 年的现在,都预言对了。社区都在扯做泛型后的多个关联组件,以及泛型可读性和结构...

显然,泛型就是双刃剑?你怎么看

若有任何疑问欢迎评论区反馈和交流,最好的关系是互相成就,各位的点赞就是煎鱼创作的最大动力,感谢支持。

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blo… 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。