首頁 > 後端開發 > Golang > 如何有效地將資料解組到 Go 中的介面類型?

如何有效地將資料解組到 Go 中的介面類型?

Susan Sarandon
發布: 2024-12-21 14:35:10
原創
284 人瀏覽過

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註解您的類型,以指定要解組的確切類型

{"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中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板