2013-12-21 15 views
5

Ich hatte ein letztes Problem mit meinem Code, der die Funktion .Call im Reflect-Paket beinhaltet.Wie man richtig verwendet. Rufen Sie im reflect-Paket, Golang?

So einen Anruf Ich mache wie folgt aus:

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

, wo die Methode, die ich die .Call mache, ist wie folgt:

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

Was ich nicht ganz zu verstehen ist, wie man die Variable "in" manipuliert, um die Karte, die ich brauche, in die Funktion zu übergeben. Ich sehe, dass der zweite Parameter in der make() die Länge des Parameters ist? Aber ich verstehe nicht ganz, wie man die Variablen formatiert, um meine Parameter richtig zu übergeben. Ich laufe rekursiv in die Fehlermeldung:

reflect: Call with too few input arguments 

Jede Hilfe würde sehr geschätzt werden!

Antwort

4

vom Value.Call documentation:..

Aufruf ruft die Funktion v mit den Eingabeargumenten auf. Wenn z. B. len(in) == 3, v.Call(in) den Go-Aufruf v(in[0], in[1], in[2]) darstellt.

Wenn Sie also eine Funktion mit einem Parameter aufrufen möchten, müssen in ein reflect.Value des richtige Art enthalten, in Ihrem Fall map[string][]string.

Der Ausdruck

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

schafft ein Stück mit einer Länge von 0, dies zu Value.Call Passing in der Panik führen Sie, wie Sie erhalten Notwendigkeit 1 Parameter nicht Null.

Das wäre richtig Aufruf sein:

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

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

myMethod.Call(in) 
+0

Ah ok, ok ich sehe, vielen Dank! :) Schätze all deine Hilfe heute! – user1493543

6

Der Aufruf versucht, Nullparameter an einen Controller zu übergeben, der einen Parameter erwartet (in ist ein leeres Segment). Sie müssen etwas mehr wie in := []reflect.Value{reflect.ValueOf(params)} tun.

Sie könnten auch .Interface() nennen, wenn Sie die Methode gefunden haben, dann Typ Behauptung verwenden ein func Sie direkt anrufen können zu erhalten:

// 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) 

(Dann könnte man sogar Cachemethod in einer Karte eingegeben von Methodennamen, so würden Sie nicht reflect Operationen nächsten Anruf zu tun haben, aber Sie müssen das nicht tun, für sie zu arbeiten)

+0

Ich verstehe Ihren letzten Absatz nicht. – nemo

+0

Entschuldigung. Code hinzugefügt Ich sage, sobald Sie die Methode gefunden haben, rufen Sie eine 'Schnittstelle {}' auf und machen Sie den Rest mit einer Typ-Assertion. – twotwotwo

+0

(@ nemo - macht das klar, was ich überhaupt gesagt habe? Selbst wenn Sie nicht denken, dass es eine gute Idee ist?) – twotwotwo