>  기사  >  백엔드 개발  >  Go에서 YAML 필드를 특정 구조체로 동적으로 구문 분석하는 방법은 무엇입니까?

Go에서 YAML 필드를 특정 구조체로 동적으로 구문 분석하는 방법은 무엇입니까?

Linda Hamilton
Linda Hamilton원래의
2024-10-28 12:58:30317검색

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]인터페이스를 사용하는 동안{ } 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.