reflect.Value.Call
を使う
package main
import (
"fmt"
"reflect"
)
func main() {
fn := func(a, b string) {
fmt.Println(a, b)
}
callback := reflect.ValueOf(fn)
args := make([]reflect.Value, 3)
args[0] = reflect.ValueOf("foo")
args[1] = reflect.ValueOf("bar")
callback.Call(args)
// => foo bar
}
引数の個数が一致していないとpanicになる
package main
import (
"fmt"
"reflect"
)
func main() {
fn := func(a, b string) {
fmt.Println(a, b)
}
callback := reflect.ValueOf(fn)
args := make([]reflect.Value, 3)
args[0] = reflect.ValueOf("foo")
args[1] = reflect.ValueOf("bar")
args[2] = reflect.ValueOf("baz")
callback.Call(args)
// => panic: reflect: Call with too many input arguments
// 少ない場合 panic: reflect: Call with too few input arguments
}
いいやり方かわからないが、個数が一致するように以下のようにしてみた。
reflect.Value.Type().NumIn()
でfuncの引数の個数がわかるreflect.New(funcType.In(i)).Elem()
でi番目の引数の型のゼロ値を取得する
package main
import (
"fmt"
"reflect"
)
func main() {
fn := func(a, b string) {
fmt.Println(a, b)
}
callback := reflect.ValueOf(fn)
args := make([]any, 0)
args = append(args, "foo")
args = append(args, "bar")
args = append(args, "baz")
funcType := callback.Type()
inputLen := funcType.NumIn()
fmt.Printf("input length for func=%d\n", inputLen)
passedArguments := make([]reflect.Value, inputLen)
for i := range len(passedArguments) {
var v any
if len(args) > i {
v = args[i]
}
if v == nil {
passedArguments[i] = reflect.New(funcType.In(i)).Elem()
} else {
passedArguments[i] = reflect.ValueOf(v)
}
}
callback.Call(passedArguments)
}