Unmarshal to Interface Type
Dans Go, le marshaling et le démarshaling des données impliquent une conversion entre des représentations en mémoire et un format sérialisé. Bien qu'il soit simple de rassembler les données des types d'interface, le démarshalage vers les types d'interface peut poser un défi.
Explication
Le démarshalage implique la création d'une instance concrète d'un type pour recevoir le données. Cependant, lors du démarshalage sur un type d'interface, le démarshaller ne peut pas déterminer le type spécifique de l'objet concret à instancier.
Solution
Pour résoudre ce problème, une approche consiste pour implémenter l'interface Unmarshaler pour les types personnalisés. En implémentant Unmarshaler, vous fournissez au unmarshaller un moyen personnalisé de créer une instance du type concret et de remplir ses champs.
type MyType struct { // ... fields } func (m *MyType) Unmarshal(data []byte) error { // Unmarshal the data into the fields of MyType return nil }
Cette méthode de démarshaling personnalisée peut ensuite être utilisée pour démarshaler les données JSON en instances de MyType. .
Vous pouvez également annoter votre type avec typeinfo pour spécifier le type exact à annuler. à.
{"Type": "YourTypeName", ...}
Exemple
Considérez le code modifié suivant :
package main import ( "encoding/json" "fmt" "log" "net" "net/rpc" "net/rpc/jsonrpc" "reflect" "time" ) type Foo interface { SayHello() error } type fakeFoo struct { internalValue string } // Implement Unmarshaler interface for fakeFoo func (f *fakeFoo) Unmarshal(data []byte) error { log.Println("Unmarshaling fakeFoo...") type tmpType fakeFoo return json.Unmarshal(data, (*tmpType)(f)) } func NewFakeFoo() *fakeFoo { f := &fakeFoo{} f.internalValue = "123456789012347" return f } func (m *fakeFoo) SayHello() error { return nil } type FooManager struct { availableFoos []Foo } func NewFooManager() *FooManager { p := new(FooManager) p.availableFoos = make([]Foo, 0) return p } func AddFoo(mm *FooManager, m Foo) { mm.availableFoos = append(mm.availableFoos, m) log.Println("Added type ", reflect.TypeOf(m)) } func (mm *FooManager) GetAvailableFoos(in []Foo, out *[]Foo) error { *out = append(in, mm.availableFoos...) return nil } func startServer(mm *FooManager) { server := rpc.NewServer() server.Register(mm) l, e := net.Listen("tcp", ":8222") if e != nil { log.Fatal("listen error:", e) } for { conn, err := l.Accept() log.Println("Incoming!") if err != nil { log.Fatal(err) } go server.ServeCodec(jsonrpc.NewServerCodec(conn)) } } func main() { fake1 := NewFakeFoo() fooHolder := NewFooManager() AddFoo(fooHolder, fake1) go startServer(fooHolder) time.Sleep(1 * time.Second) // Sleep to allow server to start log.Println("Using standard function call") var foos []Foo fooHolder.GetAvailableFoos(foos, &foos) log.Println(foos) log.Println("Using RPC call") conn, err := net.Dial("tcp", "localhost:8222") if err != nil { log.Fatalln(err) } defer conn.Close() c := jsonrpc.NewClient(conn) err = c.Call("FooManager.GetAvailableFoos", foos, &foos) if err != nil { log.Fatal("GetAvailableFoos error:", err) } log.Println("Success: ", foos) }
Lorsque vous exécutez ce code modifié, vous verrez démarshaling réussi des types d'interface sur une connexion RPC.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!