Golang:检索 YAML 中的嵌套键

sla*_*fer 5 go

这是我的YAML文件:

hosts: all
gather_facts: no
remote_user: ubuntu
name: install latest nginx
tasks:
  - name: install the nginx key
    apt_key:
      url: http://nginx.org/keys/nginx_signing.key 
      state: present
    become: yes

  - name:  install aws cli
    command: pip3 install awscli
    become: yes
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

package main

import (
    "github.com/davecgh/go-spew/spew"
    "gopkg.in/yaml.v2"
    "io/ioutil"
)

type Config struct {
    Hosts        string              `yaml:hosts`
    Gather_facts string              `yaml:gatherfacts`
    Remote_user  string              `yaml:remoteuser`
    Name         string              `yaml:names`
    Tasks        []map[string]string `yaml:tasks`
}

func main() {
    file, err := ioutil.ReadFile("/path-to-nginx1.yml")
    if err != nil {
        panic(err)
    }
    var config Config
    yaml.Unmarshal(file, &config)
    spew.Dump(config)
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

(main.Config) {
 Hosts: (string) (len=3) "all",
 Gather_facts: (string) (len=2) "no",
 Remote_user: (string) (len=6) "ubuntu",
 Name: (string) (len=20) "install latest nginx",
 Tasks: ([]map[string]string) (len=2 cap=2) {
  (map[string]string) (len=2) {
   (string) (len=6) "become": (string) (len=3) "yes",
   (string) (len=4) "name": (string) (len=21) "install the nginx key"
  },
  (map[string]string) (len=3) {
   (string) (len=4) "name": (string) (len=15) "install aws cli",
   (string) (len=7) "command": (string) (len=19) "pip3 install awscli",
   (string) (len=6) "become": (string) (len=3) "yes"
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

问题:如何从 YAML 中检索以下密钥?

apt_key:
  url: http://nginx.org/keys/nginx_signing.key 
  state: present
Run Code Online (Sandbox Code Playgroud)

目前,我的 Go 解析器在输出中完全忽略了上述键。

此外,我有许多 YAML 文件,其中都有不同程度的嵌套。大多数文件本身都有不同程度的嵌套。那么我是否struct需要进行修改才能解决每个单独的密钥问题?或者,什么是更好的处理YAML每个键具有不同级别嵌套的文件的方法?

>>> 更新 <<< :

我通过修改我的Tasks内部取得了一些进展struct,如下所示:

type Config struct {
    Hosts        string `yaml:hosts`
    Gather_facts string `yaml:gatherfacts`
    Remote_user  string `yaml:remoteuser`
    Name         string `yaml:names`
    Tasks        []struct {
        Name    string `yaml:name`
        Apt_key struct {
            Url   string `yaml:url`
            State string `yaml:url`
        } `yaml:apt_key`
        Become string `yaml:become`
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

(main.Config) {
 Hosts: (string) (len=3) "all",
 Gather_facts: (string) (len=2) "no",
 Remote_user: (string) (len=6) "ubuntu",
 Name: (string) (len=20) "install latest nginx",
 Tasks: ([]struct { Name string "yaml:name"; Apt_key struct { Url string "yaml:url"; State string "yaml:url" } "yaml:apt_key"; Become string "yaml:become" }) (len=2 cap=2) {
  (struct { Name string "yaml:name"; Apt_key struct { Url string "yaml:url"; State string "yaml:url" } "yaml:apt_key"; Become string "yaml:become" }) {
   Name: (string) (len=21) "install the nginx key",
   Apt_key: (struct { Url string "yaml:url"; State string "yaml:url" }) {
    Url: (string) (len=39) "http://nginx.org/keys/nginx_signing.key",
    State: (string) (len=7) "present"
   },
   Become: (string) (len=3) "yes"
  },
  (struct { Name string "yaml:name"; Apt_key struct { Url string "yaml:url"; State string "yaml:url" } "yaml:apt_key"; Become string "yaml:become" }) {
   Name: (string) (len=15) "install aws cli",
   Apt_key: (struct { Url string "yaml:url"; State string "yaml:url" }) {
    Url: (string) "",
    State: (string) ""
   },
   Become: (string) (len=3) "yes"
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

所以现在我可以看到apt_key之前完全丢失的部分。但是,我没有找到command用 YAML 编写的部分:

      command: pip3 install awscli
Run Code Online (Sandbox Code Playgroud)

我怎样才能得到它?

另外,我感觉不太好,因为我必须声明几乎每个键,struct在这种情况下这是可以的,因为我的YAML几乎没有 15 行长。YAML但如果更大更长的话,这将是丑陋和麻烦的。我确信一定有更好、更有效的方法来处理YAML文件。

小智 1

看起来你已经完成了所有事情,你只是错过了 Config 结构定义中的 Command 部分。我看到其他答案指出您的数据不一致,这是正确的,但您可以在同一结构中获取它们,如果 yaml 文件中缺少字段,则缺少的字段将为空。

    package main

    import (
        "github.com/davecgh/go-spew/spew"
        "gopkg.in/yaml.v2"
        "io/ioutil"
    )

    type Config struct {
        Hosts        string `yaml:hosts`
        Gather_facts string `yaml:gatherfacts`
        Remote_user  string `yaml:remoteuser`
        Name         string `yaml:names`
        Tasks        []struct {
            Name    string `yaml:name`
            Apt_key struct {
                Url   string `yaml:url`
                State string `yaml:url`
            } `yaml:apt_key`
            Become string `yaml:become`
            Command string `yaml:command`
        }
    }

    func main() {
        file, err := ioutil.ReadFile("/home/bane/Desktop/go/a.yml")
        if err != nil {
            panic(err)
        }
        var config Config
        yaml.Unmarshal(file, &config)
        // spew.Dump(config)
        spew.Dump(config.Tasks[0])
        spew.Dump(config.Tasks[1])
    }
Run Code Online (Sandbox Code Playgroud)