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 }