Skip to content

Instantly share code, notes, and snippets.

@egonelbre
Created August 23, 2017 09:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save egonelbre/62d62b65aecb4e0de0821a886c0cd0a8 to your computer and use it in GitHub Desktop.
Save egonelbre/62d62b65aecb4e0de0821a886c0cd0a8 to your computer and use it in GitHub Desktop.
Go: reflection filter (https://play.golang.org/p/LI6iZgqW7J)
package main
import (
"fmt"
"reflect"
)
func assert(k bool, msg string) {
if !k {
panic(msg)
}
}
func Filter(sliceptr interface{}, filter interface{}) {
spv := reflect.ValueOf(sliceptr)
assert(spv.Kind() == reflect.Ptr, "Filter: not pointer to slice")
sv := spv.Elem()
assert(sv.Kind() == reflect.Slice, "Filter: not pointer to slice")
et := sv.Type().Elem()
fnv := reflect.ValueOf(filter)
fnt := fnv.Type()
assert(fnt.Kind() == reflect.Func, "Filter: filter must be func")
assert(fnt.NumIn() == 1 && fnt.NumOut() == 1, "Filter: filter must have one argument and one return")
assert(et.ConvertibleTo(fnt.In(0)), "Filter: incompatible argument for type")
assert(fnt.Out(0).Kind() == reflect.Bool, "Filter: incompatible return value")
k := 0
for i := 0; i < sv.Len(); i++ {
elem := sv.Index(i)
r := fnv.Call([]reflect.Value{elem})
remove := r[0].Bool()
if remove {
continue
}
if i != k {
sv.Index(k).Set(elem)
}
k++
}
sv.SetLen(k)
}
func main() {
data := []int{1, 2, 5, 7, 2, 5, 5, 5, 5, 5, 3, 413}
Filter(&data, func(v int) bool { return v == 5 })
fmt.Println(data)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment