Sto lavorando su un sistema di template scritto in Go, il che significa che richiede un uso liberale del pacchetto reflect
. In questa circostanza specifica, devo essere in grado di chiamare dinamicamente un metodo su un interface{}
. La stranezza è che la mia logica di riflessione funziona bene finché i miei dati sono di tipo noto, ma non se i dati sono di tipo interface{}
.Chiamare dinamicamente metodo sull'interfaccia {} indipendentemente dal tipo di ricevitore
Nell'esempio seguente è possibile vedere che la logica in main()
e Pass()
è identica. L'unica differenza è se i dati sono un tipo conosciuto o un tipo noto all'interno di un gioco interface{}
Go: http://play.golang.org/p/FTP3wgc0sZ
package main
import (
"fmt"
"reflect"
)
type Test struct {
Start string
}
func (t *Test) Finish() string {
return t.Start + "finish"
}
func Pass(i interface{}) {
_, ok := reflect.TypeOf(&i).MethodByName("Finish")
if ok {
fmt.Println(reflect.ValueOf(&i).MethodByName("Finish").Call([]reflect.Value{})[0])
} else {
fmt.Println("Pass() fail")
}
}
func main() {
i := Test{Start: "start"}
Pass(i)
_, ok := reflect.TypeOf(&i).MethodByName("Finish")
if ok {
fmt.Println(reflect.ValueOf(&i).MethodByName("Finish").Call([]reflect.Value{})[0])
} else {
fmt.Println("main() fail")
}
}
Al momento l'esecuzione di questo codice si ottiene il seguente risultato
Pass() fail
startfinish
Quale significa che la mia metodologia per chiamare dinamicamente un metodo funziona bene tranne in uno scenario in cui il mio oggetto è attualmente in un interface{}
.
Se invece non utilizzo un ricevitore puntatore e passaggio i
allora funziona come previsto.
andare a giocare: http://play.golang.org/p/myM0UXVYzX
Questo mi porta a credere che il mio problema è che non riesco a accedere all'indirizzo di i (&i
) quando si tratta di un interface{}
. Ho setacciato il pacchetto di riflessione e testato cose come reflect.Value.Addr()
e reflect.PtrTo()
ma non riuscivo a far funzionare il modo in cui mi serviva. La mia impressione è che abbia qualcosa a che fare con il fatto che uno interface{}
è per definizione un oggetto di riferimento.
Grazie. Sebbene la mia domanda fosse diversa, la tua risposta mi ha aiutato a determinare se una struct ha un metodo su di essa, con 'IsValid()'. – Matt
Mi è venuto in mente questo (http://play.golang.org/p/v7lC0swB3s) quando provo a rispondere alla mia stessa domanda (http://stackoverflow.com/questions/20167935/can-embedded-methods-access-parent -campi) – Brenden