4

Go泛型编程: 支持特例化

 2 years ago
source link: https://colobu.com/2022/01/11/go-generic-supports-specialization-no/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Go泛型编程: 支持特例化

一些编程语言如C++、Rust都是支持泛型特例化的,Go泛型支持吗?

所谓特例化(specialization)对泛型功能代码的扩展。比如对于泛型的函数,它的实现对于满足泛型参数的所有类型(type set)都是一样的,如果我们想对这些类型集(type set)中的一个,它的函数做特殊的实现,一些支持泛型特例化的语言是可以支持的,比如C++ template:

template <typename T>
void fun(T a)
cout << "template fun(): " << a << endl;
template <> // 对int型特例化
void fun(int a)
cout << "specialized template fun for int type: " << a << endl;

这里fun是一个函数模板,但是针对int类型,此函数有特殊的实现。

Rust也有类似的功能:

#![feature(min_specialization)]
struct Special
x : usize,
y : usize
trait MyTrait
fn myfunc(&self);
impl<T> MyTrait for T
default fn myfunc(&self) { println!("hi"); }
impl MyTrait for Special
fn myfunc(&self) { println!("I'm special"); }
fn main() {
let spe = Special{
spe.myfunc();

这里MyTrait针对通用类型T有一个默认实现,但是针对特定的类型Special,有一个特定的实现。

其它编程语言当前还不支持特例化,但是可以通过方法重载实现类似的功能,如typescript、C#等。
另外复杂的特例化还包括部分特例化的特性。

那么问题来了,Go的泛型(类型参数)是否支持特例化呢?我们先写个例子:

type List[T any] struct {
next *List[T]
value T
func (l *List[T]) Len() int {
return 0
func (l *List[string]) Length() int {
return 0

这里我们定义了一个泛型类型List[T any], 包括它的一个泛型方法Len() int,接下来我们尝试定义一个“特例化”的方法Length() int

编译一下,没问题,程序可以正常编译,难道Go泛型真的支持特例化吗?

我们再增加一个特例化泛型方法试试:

func (l *List[int]) Size() int {
return 0

这个时候再编译试试,编译出错:

cannot use 0 (untyped int constant) as int value in return statement

其实这个错误信息已经告诉我们了,这里的int并不是内建的整数类型,而是一个类型参数的名称,等价于我们常用的TKV。这里我们使用int作为类型参数的名称很有迷惑性。

所以答案也是很明确的,当前Go 1.18并不支持泛型, 小心别掉到坑里了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK