reflection - Idiomatic way to implement generic functions in Go -


let's want write function check whether predicate matched element in slice:

func isin(array []t, pred func(elt t) bool) bool {     _, obj := range array {         if pred(obj) { return true;}     }     return false; } 

obviously, previous code won't compile, since t not exist. can replace interface{} this:

func isin(array[]interface{}, pred func(elt interface{}) bool) bool {     ... } 

as happy let predicate perform casting:

isin([]interface{}{1,2,3,4}, func(o interface{}) {return o.(int) == 3; }); 

but then, function won't accept array not of type []interface{}:

isin([]int{1,2,3,4}, func(o interface{}) { return o.(int) == 3; }) // not compile 

and similarly:

func isin(arr interface, pred func(o interface{}) bool) bool {     _, o := range arr.([]interface{}) { ... } } isin([]int{1,2,3,4}, func(o interface{}) { return o.(int) == 3; }) // panics @ runtime (cannot cast []int []interface) 

the other alternative have typed functions each array type:

isinint(arr []int, pred func(i int) bool) { ... } isinstr(arr []string, pred func(s string) bool) { ... } ... 

but seems lot of code duplication.

has come nice way deal such situations ?

edit

thanks jnml's fantastic tips on go reflection, think have found nice way express these patterns, converting every 'iterable' channel:

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() {             := 0; < v.len(); i++ {                 c<-v.index(i).interface()             }             close(c)         }()     } else if v.kind() == reflect.chan {         go func() {             x, ok := v.recv()             ok {                 c<-x.interface()                 x,ok = v.recv()             }             close(c)         }()     } else if (... whatever iteration protocol have ...) {     } else {         panic("cannot iterate !")     }     return c; } 

with initial example rewritten using on playground.

thanks lot jnml , anisus helping out !

for example:

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 slice")         }          := 0; < v.len(); i++ {                 if predicate(v.index(i)) {                         return true                 }         }          return false }  func main() {         := []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 })) } 

playground


output:

true false 

Comments

Popular posts from this blog

image - ClassNotFoundException when add a prebuilt apk into system.img in android -

I need to import mysql 5.1 to 5.5? -

Java, Hibernate, MySQL - store UTC date-time -