问题
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:
From the Value.Call documentation:
Call calls the function
v
with the input arguments in. For example, iflen(in) == 3
,v.Call(in)
represents the Go callv(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:
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.)
来源:https://stackoverflow.com/questions/20714939/how-to-properly-use-call-in-reflect-package