Dynamisches Parsen eines YAML-Felds in bestimmte Strukturen in Go
YAML-Dateien enthalten oft Felder, die durch mehrere Arten von Strukturen dargestellt werden können. Um Code und YAML-Dateien zu vereinfachen, betrachten Sie die folgenden YAML-Beispiele:
kind: "foo" spec: fooVal: 4
kind: "bar" spec: barVal: 5
Die entsprechenden Strukturen zum Parsen sind:
<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>
Bei Verwendung einer Map[string]-Schnittstelle{ } für das Spec-Feld ist eine Option, es kann bei größeren YAML-Dateien komplex werden.
Elegante Lösung mit benutzerdefiniertem Unmarshaler
Ein alternativer Ansatz besteht darin, einen benutzerdefinierten Unmarshaler für zu erstellen der Spezifikationstyp. Implementieren Sie für die Verwendung mit yaml.v2 Folgendes:
<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>
Verwenden Sie für yaml.v3 Folgendes:
<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>
Diese Lösung ordnet YAML dynamisch zu Feld basierend auf dem Feld „Art“ in die entsprechende Struktur umwandeln, sodass keine zusätzlichen Schritte oder Speicherverbrauch erforderlich sind.
Das obige ist der detaillierte Inhalt vonWie kann ich ein YAML-Feld dynamisch in bestimmte Strukturen in Go analysieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!