Generics Go中实现泛型函数的惯用方法
假设我想编写一个函数来检查谓词是否与切片中的元素匹配:Generics Go中实现泛型函数的惯用方法,generics,reflection,go,covariance,Generics,Reflection,Go,Covariance,假设我想编写一个函数来检查谓词是否与切片中的元素匹配: func IsIn(array []T, pred func(elt T) bool) bool { for _, obj := range array { if pred(obj) { return true;} } return false; } 显然,前面的代码不会编译,因为t不存在。我可以用一些接口{}替换它,如下所示: func IsIn(array[]interface{}, pred
func IsIn(array []T, pred func(elt T) bool) bool {
for _, obj := range array {
if pred(obj) { return true;}
}
return false;
}
显然,前面的代码不会编译,因为t
不存在。我可以用一些接口{}
替换它,如下所示:
func IsIn(array[]interface{}, pred func(elt interface{}) bool) bool {
...
}
我很高兴让谓词执行铸造:
IsIn([]interface{}{1,2,3,4}, func(o interface{}) {return o.(int) == 3; });
但是,函数将不接受任何不是[]接口{}
类型的数组:
IsIn([]int{1,2,3,4}, func(o interface{}) { return o.(int) == 3; }) // DO NOT COMPILE
同样地:
func IsIn(arr interface, pred func(o interface{}) bool) bool {
for _, o := range arr.([]interface{}) { ... }
}
IsIn([]int{1,2,3,4}, func(o interface{}) { return o.(int) == 3; }) // PANICS AT RUNTIME (cannot cast []int to []interface)
另一种选择是为每种数组类型提供类型化函数:
IsInInt(arr []int, pred func(i int) bool) { ... }
IsInStr(arr []string, pred func(s string) bool) { ... }
...
但似乎有很多代码重复
有没有人想出一个好办法来处理这种情况
编辑
多亏了Go reflection的绝妙技巧,我想我找到了一种表达这些模式的好方法,将每个“iterable”转换为一个频道:
func iter(obj interface{}) chan interface{} {
c := make(chan interface{})
v := reflect.ValueOf(obj)
if (v.Kind() == reflect.Array || v.Kind() == reflect.Slice) {
go func() {
for i := 0; i < v.Len(); i++ {
c<-v.Index(i).Interface()
}
close(c)
}()
} else if v.Kind() == reflect.Chan {
go func() {
x, ok := v.Recv()
for ok {
c<-x.Interface()
x,ok = v.Recv()
}
close(c)
}()
} else if (... whatever iteration protocol you have ...) {
} else {
panic("Cannot iterate !")
}
return c;
}
func iter(obj接口{})chan接口{}{
c:=make(chan接口{})
v:=反射值(obj)
if(v.Kind()==reflect.Array | | v.Kind()==reflect.Slice){
go func(){
对于i:=0;isort
包中这样做;为数组定义一个接口:
type Interface interface {
Len() int
Equal(i int, v interface{}) bool
}
func IsIn(array Interface, value interface{}) bool {
for i := 0; i < array.Len(); i++ {
if array.Equal(i, value) {
return true
}
}
return false;
}
类型接口{
Len()int
相等(i int,v接口{})bool
}
func-IsIn(数组接口,值接口{})bool{
对于i:=0;i
只要阵列实现此接口,就可以使用IsIn()
可以找到工作示例例如:
package main
import (
"fmt"
"reflect"
)
func checkSlice(slice interface{}, predicate func(reflect.Value) bool) bool {
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
panic("not a slice")
}
for i := 0; i < v.Len(); i++ {
if predicate(v.Index(i)) {
return true
}
}
return false
}
func main() {
a := []int{1, 2, 3, 4, 42, 278, 314}
fmt.Println(checkSlice(a, func(v reflect.Value) bool { return v.Int() == 42 }))
b := []float64{1.2, 3.4, -2.5}
fmt.Println(checkSlice(b, func(v reflect.Value) bool { return v.Float() > 4 }))
}
太好了!这就够了。谢谢你给我展示了这段我不懂的语言:)一个旧问题的新答案。。。
true
false