Powiedzmy chcę napisać funkcję, aby sprawdzić, czy orzeczenie jest dopasowany do elementu w plasterek:Idiomatic sposobem realizacji funkcji rodzajowe Przejdź
func IsIn(array []T, pred func(elt T) bool) bool {
for _, obj := range array {
if pred(obj) { return true;}
}
return false;
}
Oczywiście, poprzedni kod nie będzie kompilować, ponieważ T
nie istnieje. Mogę wymienić go na jakiś interface{}
tak:
func IsIn(array[]interface{}, pred func(elt interface{}) bool) bool {
...
}
Ponieważ jestem szczęśliwy pozwolić orzeczenie wykonać rzucania:
IsIn([]interface{}{1,2,3,4}, func(o interface{}) {return o.(int) == 3; });
ale wtedy funkcja nie ponosi żadnej tablicy, która nie jest od typu []interface{}
:
IsIn([]int{1,2,3,4}, func(o interface{}) { return o.(int) == 3; }) // DO NOT COMPILE
I podobnie:
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)
Drugą alternatywą jest wpisaniu funkcji dla każdego typu tablicy:
IsInInt(arr []int, pred func(i int) bool) { ... }
IsInStr(arr []string, pred func(s string) bool) { ... }
...
Ale wydaje się, że dużo kodu powielania.
Czy ktoś ma dobry sposób radzenia sobie z takimi sytuacjami?
EDIT
Dzięki jnml „fantastycznych wskazówek s DALEJ refleksji, myślę, że znalazłem dobry sposób wyrażania tych wzorów, przekształcając każdy«iterable»do kanału:
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;
}
Z moim początkowym przykładem przepisany przy użyciu go on the playground.
Wielkie dzięki za jnml i ANisus za pomoc!
Nice! To załatwia sprawę. Dzięki za pokazanie mi tej części języka, której nie znałem :) – val