Go で YAML フィールドを特定の構造体に動的に解析するにはどうすればよいですか?

Linda Hamilton
リリース: 2024-10-28 12:58:30
オリジナル
316 人が閲覧しました

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

Go で YAML フィールドを特定の構造体に動的に解析する

YAML ファイルには、複数のタイプの構造体で表すことができるフィールドが含まれることがよくあります。コードと YAML ファイルを簡素化するには、次の YAML の例を検討してください。

kind: "foo"
spec:
  fooVal: 4
ログイン後にコピー
kind: "bar"
spec:
  barVal: 5
ログイン後にコピー

解析に対応する構造体は次のとおりです。

<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>
ログイン後にコピー

map[string]interface{ Spec フィールドの } はオプションですが、YAML ファイルが大きい場合は複雑になる可能性があります。

カスタム アンマーシャラーを使用したエレガントなソリューション

別のアプローチには、カスタム アンマーシャラーを作成することが含まれます。スペックタイプ。 yaml.v2 で使用する場合は、次を実装します。

<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>
ログイン後にコピー
<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>
ログイン後にコピー

yaml.v3 の場合、次を使用します。

<code class="go">type Spec struct {
    Kind string      `yaml:"kind"`
    Spec interface{} `yaml:"-"`
}</code>
ログイン後にコピー
<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>
ログイン後にコピー

このソリューションは、YAML を動的にマップします。フィールドを「kind」フィールドに基づいて適切な構造体に変換することで、追加の手順やメモリ消費の必要性を排除します。

以上がGo で YAML フィールドを特定の構造体に動的に解析するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!