简体   繁体   English

如何正确使用.Call反映包

[英]How to properly use .Call in reflect package

Been having one last issue with my code which involves the .Call function in the reflect package. 我的代码最后一个问题涉及到反射包中的.Call函数。

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: 我正在制作.Call的方法如下:

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. 我不太明白的是如何操纵“in”变量以便将我需要的地图正确传递到函数中。 I see that the second parameter in the make() is the length of the parameter? 我看到make()中的第二个参数是参数的长度? 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! 任何帮助将非常感激!

From the Value.Call documentation : 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]) . 调用带有输入参数的函数v 。例如,如果len(in) == 3 ,则v.Call(in)表示Go调用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 . 所以,如果你想调用一个函数带有一个参数, in必须包含一个reflect.Value正确类型的,你的情况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. 创建一个长度为0的切片。将此Value.Call传递给Value.Call将导致您收到的恐慌,因为您需要1个参数,而不是零。

The correct call would be: 正确的电话会是:

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

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

myMethod.Call(in)

The call is trying to pass zero parameters to a controller that expects one param ( in is an empty slice). 该调用试图将零参数传递给期望一个参数的控制器( in是一个空切片)。 You need to do something more like in := []reflect.Value{reflect.ValueOf(params)} . 你需要做更多的事情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: 一旦找到方法,你也可以调用.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)

(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.) (然后你甚至可以在方法名称键入的地图中缓存 method ,因此你不必在下次调用时进行reflect操作。但是你不必这样做才能使它工作。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM