Bagaimana Menghuraikan Medan YAML secara Dinamik kepada Struktur Khusus dalam Go?

Linda Hamilton
Lepaskan: 2024-10-28 12:58:30
asal
316 orang telah melayarinya

How to Dynamically Parse a YAML Field to Specific Structs in Go?

Menghuraikan Medan YAML secara dinamik kepada Struktur Khusus dalam Go

Fail YAML selalunya mengandungi medan yang boleh diwakili oleh berbilang jenis struct. Untuk memudahkan kod dan fail YAML, pertimbangkan contoh YAML berikut:

kind: "foo"
spec:
  fooVal: 4
Salin selepas log masuk
kind: "bar"
spec:
  barVal: 5
Salin selepas log masuk

Struktur yang sepadan untuk menghurai ialah:

<code class="go">type Spec struct {
    Kind string      `yaml:"kind"`
    Spec interface{} `yaml:"spec"`
}

type Foo struct {
    FooVal int `yaml:"fooVal"`
}

type Bar struct {
    BarVal int `yaml:"barVal"`
}</code>
Salin selepas log masuk

Semasa menggunakan peta[rentetan]antara muka{ } untuk medan Spec ialah pilihan, ia boleh menjadi kompleks untuk fail YAML yang lebih besar.

Penyelesaian Elegan Menggunakan Custom Unmarshaler

Pendekatan alternatif melibatkan mencipta Unmarshaler tersuai untuk jenis Spec. Untuk digunakan dengan yaml.v2, laksanakan perkara berikut:

<code class="go">type yamlNode struct {
    unmarshal func(interface{}) error
}

func (n *yamlNode) UnmarshalYAML(unmarshal func(interface{}) error) error {
    n.unmarshal = unmarshal
    return nil
}

type Spec struct {
    Kind string      `yaml:"kind"`
    Spec interface{} `yaml:"-"`
}</code>
Salin selepas log masuk
<code class="go">func (s *Spec) UnmarshalYAML(unmarshal func(interface{}) error) error {
    type S Spec
    type T struct {
        S    `yaml:",inline"`
        Spec yamlNode `yaml:"spec"`
    }

    obj := &T{}
    if err := unmarshal(obj); err != nil {
        return err
    }
    *s = Spec(obj.S)

    switch s.Kind {
    case "foo":
        s.Spec = new(Foo)
    case "bar":
        s.Spec = new(Bar)
    default:
        panic("kind unknown")
    }
    return obj.Spec.unmarshal(s.Spec)
}</code>
Salin selepas log masuk

Untuk yaml.v3, gunakan yang berikut:

<code class="go">type Spec struct {
    Kind string      `yaml:"kind"`
    Spec interface{} `yaml:"-"`
}</code>
Salin selepas log masuk
<code class="go">func (s *Spec) UnmarshalYAML(n *yaml.Node) error {
    type S Spec
    type T struct {
        *S   `yaml:",inline"`
        Spec yaml.Node `yaml:"spec"`
    }

    obj := &T{S: (*S)(s)}
    if err := n.Decode(obj); err != nil {
        return err
    }

    switch s.Kind {
    case "foo":
        s.Spec = new(Foo)
    case "bar":
        s.Spec = new(Bar)
    default:
        panic("kind unknown")
    }
    return obj.Spec.Decode(s.Spec)
}</code>
Salin selepas log masuk

Penyelesaian ini memetakan YAML secara dinamik medan ke struct yang sesuai berdasarkan medan "jenis", mengalih keluar keperluan untuk langkah tambahan atau penggunaan memori.

Atas ialah kandungan terperinci Bagaimana Menghuraikan Medan YAML secara Dinamik kepada Struktur Khusus dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!