原本我以为Go添加泛型就加个type注释就可以,刚读了一遍Go generic proposal,发现要考虑的很多
提案里用C++类比,很久没写,不怎么熟悉,我用Java举例子
如下Go代码
1 | // This function is INVALID. |
这份代码问题在于,v只是T类型,编译系统无法确定T类型含有String()方法,在Go中,全部的字段都会在编译时进行解析绑定,所以Go不允许上面的写法
这是泛型系统普遍存在的问题
如下Java代码
1 | public static <T> String[] Stringify1(T[] s) { |
你的String()方法根本过不了编译,无法解析String字段
那Java是如何解决这个问题的呢?有界类型参数(Bounded Type Parameters)
1 | class StringClass<T> extends ArrayList<T> { |
通过extends硬性限定T的类型范围,这样调用String()时可正确解析。
如果Go支持泛型,那必须顺带着解决 Bounded Type Parameters 的问题,标准的解决问题引入问题解决问题循环
Go借助现有的interface来做类型约束(type constraint)
1 | type Stringer interface { |
- 运算符约束
1 | 由于T是不定类型,所以无法比较 |
那Java呢?根据我所学,Java禁止不定类型的比较,C++支持,但需要运算符重载(operator overloading)
Java中原始类型(primitive type)都被封装到对象中,就连Integer比较都需要拆箱来提取int,更何谈直接比较Object
Go从设计上就没有OOP,struct传递完全可以用pointer这个生值,而这些值天生就是可以被比较的,不能禁止
这个要说一下
这个代码s也是传递引用,我在这里不想讨论值传递和引用传递,明白的人自然能看明白
1 | public void print(String s) {} |
也就是s也是一个数值,不是对象,不过Java在你调用s之前会解引用(*s).balabalabala
1 | type s struct { |
Go官方FAQ
Why not use the syntax F
like C++ and Java?
When parsing code within a function, such as v := F, at the point of seeing the < it’s ambiguous whether we are seeing a type instantiation or an expression using the < operator. Resolving that requires effectively unbounded lookahead. In general we strive to keep the Go parser efficient.