2016-09-22 97 views
3

這是我YAML文件:Golang:檢索嵌套鍵在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 

這是我的代碼:

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) 
} 

這裏是輸出:

(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" 
    } 
} 
} 

問題:如何從我的YAML中檢索以下密鑰?

apt_key: 
    url: http://nginx.org/keys/nginx_signing.key 
    state: present 

此刻,我的Go語法分析器完全忽略了輸出中的上述鍵。

另外,我有許多YAML文件,其中嵌套的程度不同。然後大多數文件本身具有不同程度的嵌套。那麼我的struct需要修改以解決每個單獨的密鑰?或者,什麼是更好的處理YAML文件的方法,每個鍵的嵌套級別不同?

>>> UPDATE < < <:

我通過修改取得了一些進展我Tasksstruct如下內:

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` 
    } 
} 

輸出:

(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" 
    } 
} 
} 

所以現在我可以看到apt_key部分早先完全失蹤。 不過,我不覺得這是寫在YAML作爲command部分:

 command: pip3 install awscli 

如何獲得呢?

此外,我沒有得到一個不錯的感覺,因爲我必須在struct中聲明幾乎每一個鍵,在這種情況下,因爲我的YAML幾乎不是15行。但是,如果YAML越來越大,這將會是醜陋和麻煩的。 我確信必須有更好更高效的方式來處理YAML文件。

回答

1

看起來好像你已經完成了所有的事情,你只是在配置結構定義中錯過了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]) 
    } 
+0

謝謝。 +1。我試過,發現'command'在不存在的鍵中顯示爲空。我認爲這是做錯的方法。 – slayedbylucifer

1

它不工作,因爲你正在試圖解組2型動物組:姓名,易鍵,變得和名稱,命令,成爲使用相同的結構。這是不一致的。

+0

是的。我瞭解數據不一致。但它是一個有效的'YAML',我的實際'YAML'比這個更長,而且更加不一致的鍵。你能建議我怎麼處理這個問題。 – slayedbylucifer

+1

可以使用兩個單獨的結構 –

+1

如果你不能僅限於兩個結構,你可以嘗試獲取所有的鍵,然後從這些鍵獲取值 –