Unmarshaling zu Schnittstellentyp
In Go umfasst das Marshalling und Unmarshaling von Daten die Konvertierung zwischen speicherinternen Darstellungen und einem serialisierten Format. Während es einfach ist, Daten von Schnittstellentypen zu marshalieren, kann das Unmarshaling für Schnittstellentypen eine Herausforderung darstellen.
Erklärung
Unmarshaling beinhaltet das Erstellen einer konkreten Instanz eines Typs, um die zu empfangen Daten. Beim Unmarshaling auf einen Schnittstellentyp kann der Unmarshaller jedoch den spezifischen Typ des konkreten zu instanziierenden Objekts nicht bestimmen.
Lösung
Um dieses Problem zu lösen, gibt es einen Ansatz um die Unmarshaler-Schnittstelle für benutzerdefinierte Typen zu implementieren. Durch die Implementierung von Unmarshaler bieten Sie dem Unmarshaller eine benutzerdefinierte Möglichkeit, eine Instanz des konkreten Typs zu erstellen und seine Felder zu füllen.
type MyType struct { // ... fields } func (m *MyType) Unmarshal(data []byte) error { // Unmarshal the data into the fields of MyType return nil }
Diese benutzerdefinierte Unmarshaling-Methode kann dann verwendet werden, um JSON-Daten in Instanzen von MyType zu entmarshalieren .
Alternativ können Sie Ihren Typ mit „typeinfo“ annotieren, um den genauen Typ anzugeben, der aufgehoben werden soll zu.
{"Type": "YourTypeName", ...}
Beispiel
Betrachten Sie den folgenden geänderten Code:
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) }
Wenn Sie diesen geänderten Code ausführen, werden Sie sehen Erfolgreiches Unmarshaling von Schnittstellentypen über eine RPC-Verbindung.
Das obige ist der detaillierte Inhalt vonWie kann ich Daten in Go effektiv in Schnittstellentypen entmarshalieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!