インターフェイス型へのアンマーシャル
Go では、データのマーシャリングとアンマーシャリングには、メモリ内表現とシリアル化された形式の間の変換が含まれます。インターフェイス型からデータをマーシャリングするのは簡単ですが、インターフェイス型へのアンマーシャリングは課題となる可能性があります。
説明
アンマーシャリングには、データを受け取る型の具体的なインスタンスの作成が含まれます。データ。ただし、インターフェイス型にアンマーシャリングする場合、アンマーシャラーはインスタンス化する具象オブジェクトの特定の型を決定できません。
解決策
この問題を解決するには、次のようなアプローチがあります。カスタム タイプの Unmarshaler インターフェイスを実装します。 Unmarshaler を実装すると、アンマーシャラーが具象型のインスタンスを作成し、そのフィールドに値を設定するためのカスタム方法が提供されます。
type MyType struct { // ... fields } func (m *MyType) Unmarshal(data []byte) error { // Unmarshal the data into the fields of MyType return nil }
このカスタム アンマーシャリング メソッドを使用して、JSON データを MyType のインスタンスにアンマーシャリングできます。 .
または、型に typeinfo の注釈を付けて、アンマーシャリングする正確な型を指定することもできます。 to.
{"Type": "YourTypeName", ...}
例
次の変更されたコードを考えてみましょう:
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) }
この変更されたコードを実行すると、次のことがわかります。 RPC 接続を介したインターフェイス タイプのアンマーシャリングが成功しました。
以上がGo でデータを効果的にアンマーシャリングしてインターフェイス型にするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。