Maison  >  Article  >  développement back-end  >  Comment analyser dynamiquement les champs YAML dans des structures spécifiques dans Go sans utiliser de carte intermédiaire ?

Comment analyser dynamiquement les champs YAML dans des structures spécifiques dans Go sans utiliser de carte intermédiaire ?

Linda Hamilton
Linda Hamiltonoriginal
2024-10-31 01:47:01620parcourir

How do you dynamically parse YAML fields into specific structs in Go without using an intermediate map?

Analyse dynamique des champs YAML en structures spécifiques dans Go

Déterminer l'approche optimale pour analyser dynamiquement les champs YAML dans des structures prédéfinies peut être un défi courant dans Go. Examinons le scénario fourni et explorons les meilleures options disponibles.

Le défi

Étant donné les fichiers YAML avec un contenu variable et un ensemble de structures représentant différents types de données, l'objectif est d'analyser dynamiquement ces champs dans les structures appropriées. L'approche proposée implique l'utilisation d'une carte intermédiaire, mais une solution plus élégante est recherchée.

Solution

En utilisant l'analyseur Yaml YAML v2.1.0, voici une approche améliorée :

<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>

Cette solution gère avec élégance l'analyse dynamique en intégrant les champs kind et spec de la structure dans le type T. Le type yamlNode facilite le démarshaling de l'interface Spec, permettant la sélection de la structure concrète appropriée.

Approches mises à jour pour YAML v3

Pour YAML v3, une approche similaire peut être utilisée, avec ajustements mineurs :

<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>

Ces approches mises à jour fournissent une méthode plus directe et plus efficace pour analyser dynamiquement les champs YAML dans les types de structure souhaités sans avoir besoin de cartes intermédiaires ou d'étapes supplémentaires.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn