在 Go 中加载动态 yaml 结构 [关闭]

Posted

技术标签:

【中文标题】在 Go 中加载动态 yaml 结构 [关闭]【英文标题】:Load a dynamic yaml structure in Go [closed] 【发布时间】:2018-10-20 22:43:45 【问题描述】:

我正在尝试将一些 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 代码的功能?

【问题讨论】:

如上所述,我一直找不到像 Python 的 yaml.load() 这样的解决方案。我对“golang yaml”的谷歌搜索只返回了指向手动将返回的数据映射到预定义结构的结果,这不适用于该数据。您的搜索是否返回了不同的内容? 是的,Go 就是这样工作的,因为 Go 是静态类型的。 单独搜索此站点会出现***.com/questions/45549682/…、***.com/questions/46749302/…、***.com/questions/48960969/parse-a-dynamic-yaml-file、***.com/questions/45890716/…、***.com/questions/47827043/…、***.com/questions/40737122/… 等等 任何静态类型语言都无法做到这一点。你可以解组到interface,但这只是推迟了问题——现在你必须在事后进行类型断言,而不是在解组之前。 我真的看不出这个问题有资格关闭的理由 【参考方案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)
            
        
    


【讨论】:

以上是关于在 Go 中加载动态 yaml 结构 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中加载用 Jinja2 嵌套的 YAML

34.Go YAML

Ruby 在与源相同的目录中加载配置(yaml)文件

为啥核心数据不会在 swiftui 类中加载,但会在结构视图中加载

在Cassandra中加载cassandra.yaml之外的其他配置文件

如何在 spring-boot 配置中加载 application.yaml 配置以进行硒测试