Function types in Go - particular type casting to more general type -
what cast / assertion need in go in order pass function expecting generic function func(interface{}) interface{}
, more specific function func(int) int
instead?
for example, in code this, fooa
can passed makeexclamer
, not foob
:
func makeexclamer(foo func (interface{}) interface{}, n int) func () { return func() { fmt.printf("%v!!!", foo(n)) } } func fooa(x interface{}) interface{} { return x.(int)*2 } func foob(x int) int { return x * 10 } func main() { exclamera := makeexclamer(fooa, 12) exclamera() exclamerb := makeexclamer(foob, 66) // >> cannot use foob (type func(int) int) type func(interface {}) interface {} in argument makeexclamer exclamerb() }
(go playground link: https://play.golang.org/p/xgzfco0iag)
i'm not interested in alternative code structure patterns, since how want work: specific function should passed general function transformer (accepting function of type any -> any
) return general function (any -> any
). may not idiomatic in go, pattern want code follow.
to use type assertions, every possible type must enumerated in makeexclamer
:
func makeexclamer(fn interface{}, arg interface{}) func() { switch fn := fn.(type) { case func(int) int: return func() { fmt.printf("%v!!!\n", fn(arg.(int))) } case func(interface{}) interface{}: return func() { fmt.printf("%v!!!\n", fn(arg)) } default: panic("not supported") } }
to accept function of type, fn
argument declared type interface{}
. code uses type switch handle different function types.
reflection can used write more general function.
func makeexclamer(fn interface{}, arg interface{}) func() { fnr := reflect.valueof(fn) argr := reflect.valueof(arg) return func() { resultr := fnr.call([]reflect.value{argr}) fmt.printf("%v!!!\n", resultr[0].interface()) } }
Comments
Post a Comment