【问题标题】:Load a dynamic yaml structure in Go [closed]在 Go 中加载动态 yaml 结构 [关闭]
【发布时间】:2023-03-06 03:55:01
【问题描述】:

我正在尝试将一些 Python 代码转换为 Golang,但在弄清楚如何加载动态 yaml 数据时遇到了一些困难,我认为这是非常基本的。到目前为止,我发现的所有方法都提到了创建 Struct 和映射值,但这不可能,因为每次读取时我收到的数据都会不同。

这不是真正的数据(实际上是从 API 返回的),而是作为示例 yaml 文件:

[ ~]$ cat /tmp/example.yaml
Massachusetts:
  cities:
    - name: 'Boston'
      area_code: 617
    - name: 'Springfield'
    - name: 'Worcester'
Virginia:
  cities:
    - name: 'Richmond'
    - name: 'Arlington'
      landmarks:
        - 'The Pentagon'
        - 'National Airport'
        - 'Arlington National Cemetary'
  presidents:
    - 'George Washington'
    - 'Thomas Jefferson'
    - 'James Madison'
    - 'James Monroe'
    - 'William Henry Harrison'
    - 'John Tyler'
Missouri:
  rivers:
    - 'Missouri River'
    - 'Mississippi'
    - 'Arkansas River'
    - 'White River'

在 Python 中读取和操作它很简单:

#!/usr/bin/python
import yaml
with open('/tmp/example.yaml', 'r') as fh:
    data = yaml.load(fh)

print yaml.dump(data, default_flow_style=False)

由于我是 Go 新手,有谁知道我应该使用哪种技术/我应该寻找的文档可以完成这个 Python 代码的功能?

【问题讨论】:

标签: go dynamic yaml


【解决方案1】:

最受欢迎的go yaml packages 之一在他们的文档中有这个确切的例子:

package main

import (
        "fmt"
        "log"

        "gopkg.in/yaml.v2"
)

var data = `
a: Easy!
b:
  c: 2
  d: [3, 4]
`

func main() {
     m := make(map[interface{}]interface{})

     err := yaml.Unmarshal([]byte(data), &m)
     if err != nil {
         log.Fatalf("error: %v", err)
     }
     fmt.Printf("--- m:\n%v\n\n", m)
}

正如 Flimzy 在上面的评论中指出的那样,现在由您的应用来动态处理架构。我觉得这可能符合“读取模式”的条件,并且这种方法与使用静态数据定义的方法有很多权衡:

  • 类型断言/检查必须在运行时,解组后处理
  • 架构必须在逻辑和断言中进行编码,而不是在声明中
  • ??

我会质疑你是否真的有动态数据?

【讨论】:

  • 我希望他们将它们分成不同的示例(“解组 intro struct”、“解组到 map”等),因为我完全错过了解组到 map 中,这可能是我需要的对于我的具体和不幸的情况。
【解决方案2】:

如果您要使用 go struct,这是一个解决方案

package main

import (
    "gopkg.in/yaml.v2"
    "log"
    "fmt"
    "bytes"
)

type City struct {
    Name string
    AreaCode string `yaml:"area_code"`
    Landmarks []string
}

type State struct {
    Name string
    Cities []*City
    Rivers []string
    Presidents []string
}


type States map[string]*State

func (s *States) Unmarshal(data []byte) error {
    err := yaml.NewDecoder(bytes.NewReader(data)).Decode(s)
    if err != nil {
        return err
    }
    for k, v := range *s {
        v.Name= k
    }
    return nil
}

func main() {
    YAML  := `Massachusetts:
  cities:
    - name: 'Boston'
      area_code: 617
    - name: 'Springfield'
    - name: 'Worcester'
Virginia:
  cities:
    - name: 'Richmond'
    - name: 'Arlington'
      landmarks:
        - 'The Pentagon'
        - 'National Airport'
        - 'Arlington National Cemetary'
  presidents:
    - 'George Washington'
    - 'Thomas Jefferson'
    - 'James Madison'
    - 'James Monroe'
    - 'William Henry Harrison'
    - 'John Tyler'
Missouri:
  rivers:
    - 'Missouri River'
    - 'Mississippi'
    - 'Arkansas River'
    - 'White River'`


    var states States = map[string]*State{}
    err :=states.Unmarshal([]byte(YAML))
    if err != nil {
        log.Fatal("failed to decode: %v", err)
    }

    for k, v := range states {
        fmt.Printf("%v -> name: %v, presidents: %v, rivers: %v\n", k, v.Name, v.Presidents, v.Rivers)
        if len(v.Cities) > 0 {
            fmt.Printf("cities:\n")
            for _, city := range v.Cities {
                fmt.Printf("%v\n", city)
            }
        }
    }

}

【讨论】:

    猜你喜欢
    • 2021-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    • 2019-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多