2014-07-07 18 views
8

Sono un nuovo arrivato e ho combattuto con questo problema quasi tutto il giorno oggi.interface {} alla conversione del tipo di funzione

Considerando Sono questi:

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

I posso assegnare una funzione alla variabile typedObject simili:

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

Ma che devo fare è passare tale funzione gestore come un'interfaccia {} variabile e quindi convertirla in qualche modo in HandlerType che potrei chiamare in seguito

Ho provato questo ma si genera un errore:

typedHandler = object.(HandlerType) 

risultati in:

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

Fondamentalmente ho bisogno di registrare le funzioni con firme diverse senza conversione ulteriore tipo prima di registrare. Così, invece di fare questo:

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

voglio registrare i gestori in questo modo:

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

.. e non voglio coinvolgere riflessione al momento della chiamata del gestore tardi

È possibile?

Edit: Ho creato un parco giochi: http://play.golang.org/p/UlwqkHjt_P

Quindi, come ho capito non v'è alcun modo per passare qualche funzione arbitraria come interfaccia {} e quindi in qualche modo convertirlo in HandlerType o qualche altro predefinito tipo di funzione quindi potrei chiamarlo senza usare la reflection?

Edit2: ho si avvicinò con questa soluzione: http://play.golang.org/p/4gUxsgmiPf

non ci dovrebbe essere alcuna penalità prestazioni durante runtime con questo codice. Ma qualcuno può pensare a un altro modo di implementare questa funzionalità senza l'interfaccia {}?

+1

Visualizza codice completo. 'typedHandler = object. (HandlerType)' ** funzionerà ** se object (di tipo 'interface {}') contiene veramente un oggetto di 'HandlerType'. Mostra codice riproducibile nel parco giochi. – Volker

+1

Un altro: se sei un neofita di Go, dovresti evitare l''interfaccia {} '. Trova un altro modo, codice Go appropriato dello scrittore. Un nuovo arrivato che per la magia di 'interface {}' odora di traslitterazione del codice da qualche altra lingua. – Volker

+0

Ho aggiunto un parco giochi dove penso di aver chiarito cosa voglio realizzare :) – user3668351

risposta

4

Non è possibile, si tratta di un tipo diverso, si potrebbe utilizzare object.(func()), object.(func() string), ecc

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

Grazie! Ora ho come implementare ciò che volevo. http://play.golang.org/p/4gUxsgmiPf – user3668351

+0

In realtà per quel modello specifico probabilmente stai meglio usando un'interfaccia come suggerita da @Elwinar. – OneOfOne

6

C'è un certo numero di piccole idee sbagliate nella vostra domanda:

  1. Tipo l'asserzione non è usata per lanciare tipi. Tutto ciò che fa è controllare che una variabile sia del tipo dato e restituire la variabile come questo tipo sottostante. Questa operazione restituisce un errore nel tuo caso, il che è normale dato che func() non è il tipo HandlerFunc.

  2. Non è necessario eseguire alcuna operazione per passare una variabile come parametro in una funzione che accetta interface{}. Ogni tipo implementa implicitamente l'interfaccia vuota.

  3. Un func() non è un HandlerType, anche se HandlerType è definita da type HandlerType func(). La definizione non ha nulla a che fare con questo.

Quello che vuoi fare non è possibile. Non sono un esperto di riflessione, ma non credo che la riflessione possa risolvere il tuo problema.

Detto questo, il metodo di registrazione dovrebbe definire un'interfaccia che tutti gli oggetti registrati dovrebbero implementare e utilizzare questa interfaccia come tipo di parametro. Guarda il pacchetto pacchetto Register per un esempio.

Problemi correlati