如何在golang中漂亮地读取yaml的不同子类型

问题描述 投票:0回答:1

有一个多文档yaml文件,其中包含不同的文档(k8s CRD)。

我不喜欢下面的实现,看起来我正在执行不必要的解码和类型转换步骤。 帮我把 GetAll 函数写得更漂亮/更清晰。

package main

import (
    "bytes"
    "fmt"

    "gopkg.in/yaml.v3"
)

const yamldata = `
kind: Kind1
spec1: AAA
---
kind: Kind2
spec2: BBB
`

type Meta struct {
    Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`
}
type Kind1 struct {
    Meta  `json:",inline" yaml:",inline"`
    Spec1 string `json:"spec1,omitempty" yaml:"spec1,omitempty"`
}
type Kind2 struct {
    Meta  `json:",inline" yaml:",inline"`
    Spec2 string `json:"spec2,omitempty" yaml:"spec2,omitempty"`
}

func GetAll[T Kind1 | Kind2](yamldata string) (result []*T) {
    dec := yaml.NewDecoder(bytes.NewBufferString(yamldata))
    for {
        var node yaml.Node
        err := dec.Decode(&node)
        if err != nil {
            return
        }
        var meta Meta
        node.Decode(&meta)

        var t T
        switch any(t).(type) {
        case Kind1:
            if meta.Kind == "Kind1" {
                var k any = &Kind1{}
                rzlt, ok := k.(*T)
                if ok {
                    node.Decode(rzlt)
                    result = append(result, rzlt)
                }
            }
        case Kind2:
            if meta.Kind == "Kind2" {
                var k any = &Kind2{}
                rzlt, ok := k.(*T)
                if ok {
                    node.Decode(k)
                    result = append(result, rzlt)
                }
            }
        }
    }
}

func main() {
    fmt.Print(GetAll[Kind1](yamldata)[0])
    fmt.Print(GetAll[Kind2](yamldata)[0])
}

go generics yaml
1个回答
0
投票

将功能改进为以下形式。现在我喜欢她))))但是如果有更漂亮的选择,请不要犹豫写!

func GetAll[T Kind1 | Kind2](yamldata string) (result []*T) {
    dec := yaml.NewDecoder(bytes.NewBufferString(yamldata))
    for {
        var m any = new(T)
        err := dec.Decode(m)
        if err != nil {
            if err.Error() == "EOF" {
                break
            }
            continue
        }
        switch k := m.(type) {
        case *Kind1:
            if k.Kind == "Kind1" {
                result = append(result, m.(*T))
            }
        case *Kind2:
            if k.Kind == "Kind2" {
                result = append(result, m.(*T))
            }
        }
    }
    return
}
© www.soinside.com 2019 - 2024. All rights reserved.