Loading

Go1.18 - 使用函数作为泛型参数

😃 有点标题党了。

不同于C++的模版参数,Go1.18新增的泛型并不支持使用函数作为泛型参数,因为Go函数是个值,而泛型的参数只能是类型。

有什么办法可以绕过吗?

灵光一现想起了C++里面Functor(函子)的概念:

class Foo
{
public:
    void operator () (int i) { printf("Foo %d", i); }
};

Foo f
f(100);

原理很简单,就是通过重载()操作符,让类的表现像一个函数。

聪明的你应该联想到了,go里面可以定义一个空结构体类型 type Foo struct{},然后为它实现一个 Call() 方法,这样就得到一个近似于Functor(函子)的东西。

直接上代码:

package main

import "fmt"

// 实现运算的struct约束
type Compute[T any] interface {
	~struct{} // 必须是个空struct

	Call(x T, y T) (z T) // 输入 x, y 运算的到 z
}

// 运算并打印结果
func ComputeAndPrintResult[T any, C Compute[T]](x T, y T) {
	z := C{}.Call(x, y)
	fmt.Printf("%v @ %v = %v\n", x, y, z)
}

func main() {
	ComputeAndPrintResult[int, Add](2, 3) // 2 @ 3 = 5
	ComputeAndPrintResult[int, Sub](2, 3) // 2 @ 3 = -1
	ComputeAndPrintResult[int, Mul](2, 3) // 2 @ 3 = 6
}

// 加法运算
type Add struct{}

func (Add) Call(x int, y int) int { return x + y }

// 减法运算
type Sub struct{}

func (Sub) Call(x int, y int) int { return x - y }

// 乘法运算
type Mul struct{}

func (Mul) Call(x int, y int) int { return x * y }
posted @ 2022-03-19 20:23  roy2220  阅读(246)  评论(0编辑  收藏  举报