Pour un fichier YAML où un champ particulier peut être représenté par n'importe quelle valeur d'un ensemble prédéterminé de structures, un L'approche serait d'utiliser la méthode UnmarshalYAML du package YAML. Cela permet la création d'une logique de démarshaling personnalisée pour des types spécifiques.
En utilisant YAML v2, le code suivant obtient le comportement souhaité :
<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>
Pour YAML v3, utilisez le code suivant :
<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>
Cette approche fournit un moyen simple et élégant de regrouper les données YAML dans un ensemble prédéfini de structures tout en évitant étapes d'analyse supplémentaires ou consommation excessive de mémoire.
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!