如何从地图界面解析特定键?

时间:2019-04-11 15:11:13

标签: go yaml

我正在读取yaml文件,并将其解编为map[interface{}]interface{}。目标是替换yaml中的某个值,并仅替换该值来更新读入的文件。我不确定如何解析地图以获取要更改的特定键(password)。我相信您可以使用reflect,但我不确定语法100%

我正在读(config.yml)的YAML文件:

i_name: example

instances:
  - name: test-instance
    command: get
    arguments:
        hostname: localhost
        port: 203
        username: test
        password: testing123
    labels:
        env: dev
到目前为止的代码:

func replaceConfigPassword() {
    yamlFile, err := ioutil.ReadFile("config.yml")
    fatalIfErr(err)

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

    err = yaml.Unmarshal(yamlFile, &m)
    fatalIfErr(err)

    fmt.Println(m)

    val := reflect.ValueOf(m["instances"]["arguments"]["password"])
    fmt.Println("val=", val)

1 个答案:

答案 0 :(得分:1)

下面显示了如何逐步检查yaml以获取密码:

package main

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

func main() {
    in := []byte(`
i_name: example

instances:
  - name: test-instance
    command: get
    arguments:
        hostname: localhost
        port: 203
        username: test
        password: testing123
    labels:
        env: dev
`)

    m := make(map[string]interface{})
    if err := yaml.Unmarshal(in, &m); err != nil {
        panic(err)
    }
    fmt.Printf("%+v\n", m)

    instances := m["instances"].([]interface{})
    fmt.Printf("%+v\n", instances)

    first := instances[0]
    fmt.Printf("%+v\n", first)

    arguments := first.(map[interface{}]interface{})["arguments"]
    fmt.Printf("%+v\n", arguments)

    password := arguments.(map[interface{}]interface{})["password"]
    fmt.Printf("%+v\n", password)
}
$ go run main.go
map[i_name:example instances:[map[name:test-instance command:get arguments:map[password:testing123 hostname:localhost port:203 username:test] labels:map[env:dev]]]]
[map[name:test-instance command:get arguments:map[hostname:localhost port:203 username:test password:testing123] labels:map[env:dev]]]
map[name:test-instance command:get arguments:map[hostname:localhost port:203 username:test password:testing123] labels:map[env:dev]]
map[username:test password:testing123 hostname:localhost port:203]
testing123

如果您事先了解输入结构,则另一个选择是显式建模:

type Config struct {
    IName string `yaml:"i_name"`
    Instances []struct{
        Name string
        Command string
        Arguments map[string]interface{}
        Labels map[string]string
    }
}

    var c Config
    if err := yaml.Unmarshal(in, &c); err != nil {
        panic(err)
    }
    fmt.Printf("%+v\n", c)
    fmt.Printf("%+v\n", c.Instances[0].Arguments["password"])
$ go run main.go

{IName:example Instances:[{Name:test-instance Command:get Arguments:map[hostname:localhost port:203 username:test password:testing123] Labels:map[env:dev]}]}
testing123