英文:
How to properly use .Call in reflect package
问题
我正在使用reflect包中的.Call函数时遇到了一个问题。
我正在进行如下的调用:
params := "some map[string][]string"
in := make([]reflect.Value,0)
return_values := reflect.ValueOf(&controller_ref).MethodByName(action_name).Call(in)
我要调用的方法如下:
func (c *Controller) Root(params map[string][]string) map[string]string{}
我不太明白如何操作"in"变量以正确传递我需要的映射到函数中。我看到make()函数的第二个参数是参数的长度?但我不太明白如何格式化变量以正确传递我的参数。我一直遇到递归运行错误信息:
reflect: Call with too few input arguments
非常感谢任何帮助!
英文:
Been having one last issue with my code which involves the .Call function in the reflect package.
So I'm making a call such as this:
params := "some map[string][]string"
in := make([]reflect.Value,0)
return_values := reflect.ValueOf(&controller_ref).MethodByName(action_name).Call(in)
where the method I'm making the .Call to is as follows:
func (c *Controller) Root(params map[string][]string) map[string] string{}
What I don't quite understand is how to manipulate the "in" variable in order to properly pass the map I need to into the function. I see that the second parameter in the make() is the length of the parameter? But I don't quite understand how to format the vars in order to properly pass in my parameter. I am recursively running into the error message:
reflect: Call with too few input arguments
Any help would be much appreciated!
答案1
得分: 15
从Value.Call文档
中可以得知:
> Call方法使用输入参数in调用函数v。例如,如果len(in) == 3
,那么v.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)
英文:
From the Value.Call documentation
:
> Call calls the function v
with the input arguments in. For example, if len(in) == 3
, v.Call(in)
represents the Go call v(in[0], in[1], in[2])
.
So if you want to call a function with one parameter, in
must contain one reflect.Value
of the
right type, in your case map[string][]string
.
The expression
in := make([]reflect.Value,0)
creates a slice with length 0. Passing this to Value.Call
will result in the panic you receive as you
need 1 parameter, not zero.
The correct call would be:
m := map[string][]string{"foo": []string{"bar"}}
in := []reflect.Value{reflect.ValueOf(m)}
myMethod.Call(in)
答案2
得分: 11
调用尝试将零个参数传递给一个期望一个参数的控制器(in
是一个空切片)。你需要做一些类似于in := []reflect.Value{reflect.ValueOf(params)}
的操作。
你还可以在找到方法后调用.Interface()
,然后使用类型断言来获取一个可以直接调用的func
:
// 获取方法的 reflect.Value
methodVal := reflect.ValueOf(&controller_ref).MethodByName(action_name)
// 将其转换为 interface{}
methodIface := methodVal.Interface()
// 将其转换为具有预期签名的函数
method := methodIface.(func(map[string][]string) map[string]string)
// 直接调用该方法
res := method(params)
(然后,你甚至可以通过以方法名称为键将method
缓存到一个映射中,这样你就不必在下一次调用时进行reflect
操作。但这不是必须的,它仍然可以正常工作。)
英文:
The call is trying to pass zero parameters to a controller that expects one param (in
is an empty slice). You need to do something more like in := []reflect.Value{reflect.ValueOf(params)}
.
You could also call .Interface()
once you've found the method, then use type assertion to get a func
you can call directly:
// 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)
(Then you could even cache method
in a map keyed by method name, so you wouldn't have to do reflect
operations next call. But you don't have to do that for it to work.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论