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]인터페이스를 사용하는 동안{ } Spec 필드에 대한 옵션은 더 큰 YAML 파일의 경우 복잡해질 수 있습니다.
Custom Unmarshaler를 사용한 우아한 솔루션
대체 접근 방식은 Spec 필드에 대한 사용자 정의 Unmarshaler를 생성하는 것입니다. 사양 유형. 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!