ホームページ > バックエンド開発 > Golang > Go でデータを効果的にアンマーシャリングしてインターフェイス型にするにはどうすればよいですか?

Go でデータを効果的にアンマーシャリングしてインターフェイス型にするにはどうすればよいですか?

Susan Sarandon
リリース: 2024-12-21 14:35:10
オリジナル
321 人が閲覧しました

How Can I Effectively Unmarshal Data to Interface Types in Go?

インターフェイス型へのアンマーシャル

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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート