如何正确使用.Call反映包

时间:2013-12-21 02:57:30

标签: function go reflection parameters go-reflect

我的代码最后一个问题涉及到反射包中的.Call函数。

所以我正在打这样的电话:

params := "some map[string][]string"
in := make([]reflect.Value,0)
return_values := reflect.ValueOf(&controller_ref).MethodByName(action_name).Call(in)

我正在制作.Call的方法如下:

func (c *Controller) Root(params map[string][]string) map[string] string{}

我不太明白如何操纵“in”变量以便将我需要的地图正确传递到函数中。我看到make()中的第二个参数是参数的长度?但我不太明白如何格式化变量以正确传递我的参数。我递归地遇到错误消息:

reflect: Call with too few input arguments

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:9)

来自Value.Call documentation

  

调用带有输入参数的函数v。例如,如果len(in) == 3v.Call(in)代表Go调用v(in[0], in[1], in[2])

因此,如果您想使用一个参数调用函数,in必须包含一个reflect.Value 正确的类型,在您的情况下map[string][]string

表达式

in := make([]reflect.Value,0)

创建一个长度为0的切片。将其传递给Value.Call将导致您收到的恐慌 需要1个参数,而不是零。

正确的电话会是:

m := map[string][]string{"foo": []string{"bar"}}

in := []reflect.Value{reflect.ValueOf(m)}

myMethod.Call(in)

答案 1 :(得分:7)

调用试图将零参数传递给期望一个参数的控制器(in是一个空切片)。您需要执行更像in := []reflect.Value{reflect.ValueOf(params)}

的操作

您也可以在找到方法后调用.Interface(),然后使用类型断言获取可以直接调用的func

// get a reflect.Value for the method
methodVal := reflect.ValueOf(&controller_ref).MethodByName(action_name)
// turn that into an interface{}
methodIface := methodVal.Interface()
// turn that into a function that has the expected signature
method := methodIface.(func(map[string][]string) map[string]string)
// call the method directly
res := method(params)

(然后你甚至可以在按方法名称键入的地图中缓存 method,这样你就不必在下次通话时进行reflect操作。但是你不要必须这样做才能发挥作用。)