为什么Go中没有泛型?

117 generics functional-programming go

免责声明:我现在只玩了一天Go,所以很有可能我错过了很多.

有没有人知道为什么在Go中没有真正支持generics/templates/whatsInAName?所以有一个泛型map,但是由编译器提供,而Go程序员不能编写自己的实现.尽管所有关于使Go尽可能正交的讨论,为什么我可以使用泛型类型但不创建新类型?

特别是在涉及函数式编程时,有lambda,甚至是闭包,但是对于缺少泛型的静态类型系统,我如何编写,以及通用的高阶函数,如filter(predicate, list)?好的,链接列表等可以interface{}牺牲类型安全性来完成.

由于对SO/Google的快速搜索没有透露任何见解,所以看起来像仿制药,如果有的话,将作为事后补充添加到Go.我确实相信Thompson比Java家伙更好,但为什么要保持泛型?或者他们是否有计划而尚未实施?

Vin*_*enz 74

你会在这里找到这个答案:http://golang.org/doc/faq#generics

为什么Go没有泛型类型?

可能会在某些时候添加泛型.尽管我们了解一些程序员,但我们对他们并不感到紧迫.

泛型很方便,但它们在类型系统和运行时的复杂性方面付出了代价.我们还没有找到一种能够与复杂性成比例的设计,尽管我们会继续考虑它.同时,Go的内置映射和切片,以及使用空接口构造容器(具有显式拆箱)的能力意味着在许多情况下可以编写执行泛型将启用的代码,如果不太顺利的话.

这仍然是一个未决问题.

  • @amoebe,"空接口",拼写为`interface {}`,是最基本的接口类型,每个对象都提供它.如果你创建一个容器,它可以接受任何(非原始)对象.所以它非常类似于在Java中持有`Objects`的容器. (14认同)
  • @YinWang Generics在类型推断环境中并不那么简单.更重要的是; interface {}不等同于C中的void*指针.更好的类比是C#的System.Object或Objective-C的id类型.类型信息被保留,可以"强制转换"(实际上是断言)回到其具体类型.在此处获取详细信息:http://golang.org/ref/spec#Type_assertions (4认同)
  • @ChristopherPfohl我认为只有Java泛型有原始类型的装箱/拆箱问题?C#的具体通用没有问题. (3认同)
  • @tbone C#的System.Object(或Java的Object本身)本质上就是我所说的"C的void指针"(忽略那些你不能用那些语言做指针算术的部分).那些是静态类型信息丢失的地方.演员阵容无济于事,因为您将收到运行时错误. (2认同)

use*_*610 30

去2

https://blog.golang.org/go2draft上有一个泛型设计草案.

去1

Go老兵之一的Russ Cox撰写了一篇名为The Generic Dilemma博客文章,他在文章中写道

...你想要慢速程序员,慢速编译器和膨胀的二进制文件,还是执行时间慢?

慢速编程器是没有泛型的结果,编译器速度慢是由C++引起的泛型和缓慢的执行时间源于Java使用的装箱拆箱方法.

博客中没有提到的第四种可能性是C#路线.像在C++中一样生成专用代码,但在运行时需要它.我非常喜欢它,但Go与C#非常不同,所以这可能根本不适用...

我应该指出,使用流行的Java 1.4等技术在旅途中泛型编程 是强制转换成interface{}从完全一样的问题,装箱拆箱遭受(因为这是我们正在做的),除了编译时类型安全的损失.对于小类型(如整数),Go优化interface{}类型,以便转换为接口{}的整数列表占用连续的内存区域,并且只占用正常整数的两倍.interface{}但是,在进行转换时仍然存在运行时检查的开销.参考.

所有添加通用支持的项目(其中有几个都很有趣)统一进行编译时代码生成的C++路径.


Ale*_*der 9

尽管泛型当前不是内置的,但是go有几种外部泛型实现,它们将注释与生成代码的小实用程序结合使用.

这是一个这样的实现:http://clipperhouse.github.io/gen/