Unmarshal to Interface Type
In Go, marshaling dan unmarshaling data melibatkan penukaran antara representasi dalam memori dan format bersiri. Walaupun mudah untuk mengarsel data daripada jenis antara muka, unmarshaling kepada jenis antara muka boleh menimbulkan cabaran.
Penjelasan
Unmarshaling melibatkan mencipta contoh konkrit jenis untuk menerima data. Walau bagaimanapun, apabila unmarshaller kepada jenis antara muka, unmarshaller tidak boleh menentukan jenis khusus objek konkrit untuk dijadikan instantiat.
Penyelesaian
Untuk menyelesaikan isu ini, satu pendekatan ialah untuk melaksanakan antara muka Unmarshaler untuk jenis tersuai. Dengan melaksanakan Unmarshaler, anda menyediakan cara tersuai untuk unmarshaler mencipta tika jenis konkrit dan mengisi medannya.
type MyType struct { // ... fields } func (m *MyType) Unmarshal(data []byte) error { // Unmarshal the data into the fields of MyType return nil }
Kaedah unmarshaler tersuai ini kemudiannya boleh digunakan untuk menyahmarshal data JSON ke dalam tika MyType .
Sebagai alternatif, anda boleh menganotasi jenis anda dengan typeinfo untuk menentukan jenis yang tepat kepada unmarshal to.
{"Type": "YourTypeName", ...}
Contoh
Pertimbangkan kod yang diubah suai berikut:
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) }
Apabila anda menjalankan kod yang diubah suai ini, anda akan lihat berjaya membongkar jenis antara muka melalui sambungan RPC.
Atas ialah kandungan terperinci Bagaimanakah Saya Boleh Menghapuskan Data Secara Berkesan kepada Jenis Antara Muka dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!