【问题标题】:Golang and yaml with dynamic schema具有动态模式的 Golang 和 yaml
【发布时间】:2018-01-14 22:09:46
【问题描述】:

我有一个带有动态模式的 YAML 结构,例如我可以有以下yaml:

array:
  - name: myvar
    val: 1
  - name: mymap
    val: [ 1, 2]

Goyaml 将 yaml 映射到 Go 结构,它应该声明明确的类型。这里,val 要么是一个符号数,要么是一个数组,甚至是一个映射。

这种情况的最佳解决方案是什么?

【问题讨论】:

  • 您尝试将interface{} 用作val 的类型吗?
  • 具体来说,你可以使用interface{}作为类型,然后使用类型开关(tour.golang.org/methods/16)来使用它。
  • @RayfenWindspear,TehSphinX 谢谢,这种方法没有缺点吗?
  • 我认为没有其他方法,除非您更改 yaml 并为变量指定不同的名称。如果你有一个interface{} 类型的变量,你将不得不稍后根据它的类型来转换它。这有点工作,但你在下面得到了很好的建议。
  • @TehSphinX 正确,处理interface{} 值有点痛苦,但 go 的优点是它是静态类型的,但您可以执行这种伪松散类型。不过,必须付出额外的努力才能完成。

标签: parsing go yaml


【解决方案1】:

我决定添加一个显示类型断言的答案,而不是 reflect 包。您可以决定哪个最适合您的应用。我个人更喜欢内置函数而不是 reflect 包的复杂性。

var data = `
array:
  - name: myvar
    val: 1
  - name: mymap
    val: [1, 2]
`

type Data struct {
    Array []struct {
        Name string
        Val  interface{}
    }
}

func main() {
    d := Data{}
    err := yaml.Unmarshal([]byte(data), &d)
    if err != nil {
        log.Fatal(err)
    }

    for i := range d.Array {
        switch val := d.Array[i].(type) {
        case int:
            fmt.Println(val) // is integer
        case []int:
            fmt.Println(val) // is []int
        case []string:
            fmt.Println(val) // is []string
            //  .... you get the idea
        default:
            log.Fatalf("Type unaccounted for: %+v\n", d.Array[i])
        }
    }

}

【讨论】:

  • 为了使您的答案完美,您能否添加如何将interface{} 类型的Val 转换为int[]int[]string 等类型的变量?跨度>
  • 它们转换在 switch 语句中。在他们各自的情况下val实际上是正确的类型。
  • 如果您需要将单个变量断言为您知道它应该是的东西(或者您认为哈哈),您可以使用类型断言。 tour.golang.org/methods/15
  • for i := range t.Array { 应该是for i := range d.Array { 不是吗?另外,go 中的单个 char 变量名称是什么?
  • @Steve 谢谢,我在代码编辑器之外做了一些更改,结果泄露了。没有内置的 yaml 包没有帮助,所以我不能做游乐场。
猜你喜欢
  • 2018-05-29
  • 1970-01-01
  • 1970-01-01
  • 2021-10-23
  • 1970-01-01
  • 1970-01-01
  • 2015-11-15
  • 1970-01-01
  • 2021-04-13
相关资源
最近更新 更多