https://draveness.me/whys-the-design-go-generics/
泛型困境
泛型困境使我们必须在开发效率、编译速度和运行速度三者中选择两个;
目前社区中的 Go 语言方案都是有缺陷的,而 Go 团队认为泛型的支持不够紧急;
对于泛型编程的通常有以下三种处理方式:
1.(C语言)放弃泛型。这样苦了程序员
,但是也降低了语言的复杂性。
2.(C++语言)编译期特化或者大量地展开代码。这样苦了编译器。编绎器生成一堆代码,而大部分是无用的,需要一个很好的链接器去清除重复的副本。为每一个类型生成一份代码,也许这样会让代码执行更高效
,但是程序是一个整体,这样会造成对cpu的cache不友好。我曾听说一个简单的库修正和移除了模板后,text段(即动态链接库的文件格式中的text段)的大小从M级降到10K。
3.(Java语言)隐式地把所有东西装箱。这样苦了程序,执行起来会变慢
对比C语言的手写,C++语言的编译器生成,Java代码量最少,但是时空上最低效,无论是从时间还是空间来说。因为所有的操作都要隐式地装箱和拆箱。一个byte的vector容器(Vector<Byte>)所占的空间比远超一个byte。想要隐藏装箱和拆箱会让类型系统变复杂。从另一个方面来说,这个也许是指令cache友好的,因为它把一个byte的vector(Vector<Byte>)可以分开来写每一个byte。
package sort
func Float64s(a []float64)
func Strings(a []string)
func Ints(a []int)
上述函数都是 sort 包提供的,它们的功能非常相似,底层的实现也使用了近乎相同的逻辑,但是由于传入类型的不同却需要对外提供多个函数。Java 的泛型就解决了这个问题
public class ArraySortViaComparable {
public <E extends Comparable> void insertionSort(E[] a) {
for (int i = 1; i < a.length; i = i + 1) {
Comparable itemToInsert = a[i];
int j = i;
while (j != 0 && greaterThan(a[j-1], itemToInsert)) {
a[j] = a[j-1]
j = j - 1
};
a[j] = itemToInsert;
}
}
private static boolean greaterThan(E left, Object right) {
return left.compareTo(right) == 1; }
}
这段 Java 代码使用泛型数组作为参数实现了通用的数组排序逻辑,任意类型只要实现了 Comparable 接口,insertionSort 函数就能排序由该对象组成的数组。使用泛型能够减少重复的代码和逻辑,为工程师提供更强的表达能力从而提升效率。
有疑问加站长微信联系(非本文作者)