2014-07-07 23 views
8

Ich bin ein Go-Neuling und ich habe heute fast den ganzen Tag mit diesem Problem gekämpft.Schnittstelle {} zur Funktion Typ Umwandlung

Unter Berücksichtigung Ich habe diese:

type HandlerType func() 
var object interface{} 
var typedObject HandlerType 

I kann eine Funktion der typedObject Variable wie folgt vergeben:

typedHandler = func() { 
    fmt.Println("in a handler!\n") 
} 

Aber was ich tun müssen, ist, dass die Handler-Funktion passieren, wie eine Schnittstelle {} Variable und dann irgendwie in HandlerType konvertieren, die ich später anrufen könnte

Ich habe das aber versucht es wirft einen Fehler:

typedHandler = object.(HandlerType) 

Ergebnisse in:

interface conversion: interface is func(), not main.HandlerType

Grundsätzlich muss ich vor der Registrierung ohne zusätzliche Typkonvertierungsfunktionen mit unterschiedlichen Signaturen registrieren. Anstatt also, dies zu tun:

registerHandler(HandlerTypeString(func() string { ... })) 
registerHandler(HandlerTypeVoid(func() { ... })) 

Ich möchte Handler registrieren wie folgt aus:

registerHandler(func() string { ... }) 
registerHandler(func() { ... }) 

.. und ich will nicht Reflexion zum Zeitpunkt eines Handlers Aufruf beteiligen später

Ist es möglich?

bearbeiten: Ich habe einen Spielplatz erstellt: http://play.golang.org/p/UlwqkHjt_P

So wie ich verstehe, dass es keine Möglichkeit gibt, eine beliebige Funktion als Schnittstelle {} und dann irgendwie wandeln es in HandlerType oder einem anderen vordefinierten passieren Funktionstyp, so dass ich es ohne Reflektion aufrufen könnte?

EDIT2: Ich habe kam mit dieser Lösung: http://play.golang.org/p/4gUxsgmiPf

Es nicht mit diesem Code keine Leistungseinbußen während der Laufzeit sein sollte. Aber kann jemand einen anderen Weg vorstellen, diese Funktionalität ohne Schnittstelle {} zu implementieren?

+1

anzeigen zu tun. 'typedHandler = object. (HandlerType)' ** wird ** funktionieren, wenn das Objekt (vom Typ 'interface {}') wirklich ein Objekt 'HandlerType' enthält. Zeige Code, der auf dem Spielplatz spielbar ist. – Volker

+1

Noch eins: Wenn du ein Go-Neuling bist, solltest du 'interface {}' vermeiden. Finden Sie einen anderen Weg, Autor richtiger Go-Code. Ein Newcomer, der für 'interface {}' magie wie Codetranskription aus einer anderen Sprache riecht. – Volker

+0

Ich habe einen Spielplatz hinzugefügt, wo ich denke, ich habe klar gemacht, was ich erreichen möchte :) – user3668351

Antwort

4

Sie nicht können, es ist eine andere Art, könnte man einfach object.(func()) verwenden, object.(func() string) usw.

func main() { 
    type HandlerType func() 
    var object interface{} = func() { 
     fmt.Println("eureka!") 
    } 
    if f, ok := object.(func()); ok { 
     HandlerType(f)() 
    } 
} 
+0

Danke! Jetzt habe ich umgesetzt, was ich wollte. http://play.golang.org/p/4gUxsgmiPf – user3668351

+0

Eigentlich für dieses spezielle Muster sind Sie wahrscheinlich besser dran mit einem Interface wie @ Elwinar vorgeschlagen. – OneOfOne

6

Es gibt eine Reihe von kleinen Missverständnisse in Ihrer Frage ist:

  1. Typ Assertion wird nicht zum Umwandeln von Typen verwendet. Es überprüft nur, ob eine Variable vom angegebenen Typ ist, und gibt die Variable als diesen zugrunde liegenden Typ zurück. Diese Operation gibt in Ihrem Fall einen Fehler zurück, was normal ist, da func() nicht der Typ HandlerFunc ist.

  2. Sie müssen nichts tun, um eine Variable als Parameter in einer Funktion zu übergeben, die interface{} akzeptiert. Jeder Typ implementiert implizit die leere Schnittstelle.

  3. A func() ist kein HandlerType, auch wenn HandlerType von type HandlerType func() definiert ist. Die Definition hat damit nichts zu tun.

Was Sie tun möchten, ist nicht möglich. Ich bin kein Experte in der Reflexion, aber ich denke nicht, dass Reflexion Ihr Problem auch lösen könnte.

Das heißt, Ihre Registrierungsmethode sollte eine Schnittstelle definieren, die alle registrierten Objekte implementieren sollten, und diese Schnittstelle als Parametertyp verwenden. Sehen Sie sich das database/sql Paket Register Methode für ein Beispiel an.