2017-07-30 6 views
0

Kann jemand erklären, was in diesem Kern passiert? Ich verstehe das Konzept von Decorators und wie diese Implementierung einen generischen Decorator erzeugt, aber ich bin in ein paar Abschnitten wenig verloren (inline kommentiert). Würde es wirklich schätzen, wenn jemand es für mich kaputt machen könnte. Auch wenn dies nicht der beste Weg ist, einen generischen Dekorator zu schreiben, was ist das? Ich suche nach einem Dekorator, der eine Funktion des Typs func (args ... Schnittstelle {}) schmücken kann (Schnittstelle {}, Fehler), ohne Typsicherheit wegzuwerfen.Ein generischer Golang-Dekorator (Klärung erforderlich für einen Kern)

https://gist.github.com/saelo/4190b75724adc06b1c5a

package main 

import (
    "fmt" 
    "reflect" 
) 

func Decorate(impl interface{}) interface{} { 
     fn := reflect.ValueOf(impl) 
     //What does inner do ? What is this codeblock ? 
     inner := func(in []reflect.Value) []reflect.Value { //Why does this return the same type as the parameters passed to the function ? Does this mean this decorator only works for fns with signature func (arg TypeA) TypeA and not func (arg TypeA) TypeB ? 
      f := reflect.ValueOf(impl) 

      fmt.Println("Stuff before") 
      // ... 

      ret := f.Call(in) //What does call do ? Why cant we just use f(in) ? 

      fmt.Println("Stuff after") 
      // ... 

      return ret 
     } 

     v := reflect.MakeFunc(fn.Type(), inner) 

     return v.Interface() 
} 

var Add = Decorate(
    func (a, b int) int { 
     return a + b 
    }, 
).(func(a, b int) int) //Is this a type assertion ? 



func main() { 
    fmt.Println(Add(1, 2)) 
} 

Antwort

1

Die Variable inner deklariert eine short variable declaration verwenden. Die Variable inner hat den Typ func(in []reflect.Value) []reflect.Value. Der Wert ist das Funktionsliteral im Code.

Der Typ func(in []reflect.Value) []reflect.Value repräsentiert eine generische Funktion, die durch Reflektion implementiert wird. Die Funktion nimmt eine möglicherweise leere Scheibe von Argumenten und gibt eine möglicherweise leere Scheibe von Ergebnissen zurück.

Die reflect.Value für eine Funktion ist nicht direkt aufrufbar. Die Methode Call wird verwendet, um die Funktion im Wert aufzurufen.

Die .(func(a, b int) int) ist eine Typassertion.

+0

Also würde dies die Typ Assertion jedes Mal erfordern, wenn ich den Dekorator verwenden möchte? Scheint etwas klobig. Gibt es eine Möglichkeit, etwas zu tun, indem man eine Art Dekorator für 'func (args ... interface {}) erstellt (Schnittstelle {}, error)'? Ich suche nach einem generischen Logging Decorator, der nicht an eine bestimmte Funktionssignatur gebunden ist. – nitimalh

+0

@nitimalh Sie können eine Funktion erstellen, die eine beliebige Anzahl von 'interface {}' - Werten akzeptiert, aber Sie können 1, 2, 10 usw. Werte zurückgeben, einige geben auch 'bool',' error', 'zurück int' usw.? Der Kern nimmt an, dass ein einzelner Wert zurückgegeben wird, aber mehrere Werte können von einer anderen Funktion zurückgegeben werden. Dies erfordert im Wesentlichen den gleichen Code, außer dass die Rücksignatur der Funktion unterschiedlich ist. Es gibt keine Möglichkeit, dass ich das momentan beheben kann. Das heißt natürlich nicht, dass es nicht getan werden kann. Ich kann mir einfach keine realisierbare Implementierung vorstellen. –

+0

Ja, ich stimme zu. Das ist das Dilemma. Ich muss einen generischen Logging Decorator implementieren. Vielleicht gibt es einige andere Muster/Tricks, um das zu erreichen? – nitimalh

Verwandte Themen