【问题标题】:Reading a slice of maps with Golang Viper使用 Golang Viper 读取一片地图
【发布时间】:2016-12-21 16:33:13
【问题描述】:

我正在使用这里的优秀 viper 库:https://github.com/spf13/viper

我正在尝试读取 hcl 中的配置文件(尽管它也可能是 JSOn 或 YAML 文件),如下所示:

interval = 10
statsd_prefix = "pinger"



group "dns" {
  target_prefix = "ping"
  target "dns" {
    hosts = [
      "dnsserver1",
      "dnsserver2"
    ]
  }
}

到目前为止,我的代码如下所示:

viper.SetConfigName("config")
viper.AddConfigPath(".")

err := viper.ReadInConfig()

if err != nil {
  panic(fmt.Errorf("Fatal error config file: %s \n", err))
}

interval := viper.GetInt("interval")
prefix := viper.GetString("statsd_prefix")

groups := viper.GetStringMap("group")

fmt.Println(interval)
fmt.Println(prefix)

我遇到的最大问题是组选项。这可以是多个不同的组。

当我使用viper.GetStringMap 读取它时,它似乎不起作用,所以我使用了标准的viper.Get 函数。转储时生成的结构如下所示:

([]map[string]interface {}) (len=1 cap=1) {
 (map[string]interface {}) (len=1) {
  (string) (len=3) "dns": ([]map[string]interface {}) (len=1 cap=2) {
   (map[string]interface {}) (len=2) {
    (string) (len=13) "target_prefix": (string) (len=4) "ping",
    (string) (len=6) "target": ([]map[string]interface {}) (len=1 cap=1) {
     (map[string]interface {}) (len=1) {
      (string) (len=8) "dns": ([]map[string]interface {}) (len=1 cap=1) {
       (map[string]interface {}) (len=1) {
        (string) (len=5) "hosts": ([]interface {}) (len=2 cap=2) {
         (string) (len=18) "dnsserver1",
         (string) (len=18) "dnsserver2"
        }
       }
      }
     }
    }
   }
  }
 }
}

当我使用反射时,它似乎是切片类型。我需要把它切成一片吗?我怎么做?有没有更简单的方法来管理这样的数据结构?

我是 golang 的新手,所以请放轻松:)

【问题讨论】:

    标签: go


    【解决方案1】:

    我建议先描述你想要的配置结构,而不是调用 raw Get 然后决定你得到什么,比如

    type config struct {
        interval int `mapstructure:"Interval"`
        statsdPrefix string `mapstructure:"statsd_prefix"`
        groups []group
    }
    type group struct {
        group string `mapstructure:"group"`
        targetPrefix string `mapstructure:"target_prefix"`
        targets []target
    }
    type target struct {
        target string `mapstructure:"target"`
        hosts []string `mapstructure:"hosts"`
    }
    

    然后在其中解组(解码)

    var C config
    
    err := viper.Unmarshal(&C)
    if err != nil {
        t.Fatalf("unable to decode into struct, %v", err)
    }
    

    假设解码器足够聪明,可以在可能且有意义的情况下解开所提供的结构。

    【讨论】:

    • 解组后,如何使这些值可用?
    • 值可以作为 interv:=C.interval 或在循环中用于 grp:=range C.groups{ for trg:=range grp{...}} 错误很可能是导致错字-将所有摸索更改为确定。
    • 我不认为这是一个错字,无论下一个结构的名称如何,它都会发生。我认为这是因为所有这些代码都在 main.go 中?
    【解决方案2】:

    这个问题有点老了,但我想,既然我偶然发现了这个,其他人可能会来这里寻找......

    原始问题的主要问题是这个 JSON 表示法定义了一个列表,而不是一个地图:

    hosts = [
          "dnsserver1",
          "dnsserver2"
        ]
    

    所以这种情况下的简单解决方案不是使用viper.GetStringMap("group"),而是使用viper.GetStringSlice("group")

    GO 中的切片是大多数其他编程语言所称的数组或列表。 所以在这种情况下,切片将是["dnsserver1", "dnsserver2"]

    如果你想正确使用viper的GetStringMap()功能,你需要在你的配置文件中使用不同的格式,即map格式:

    "hosts": {
        "dnsserver1": "8.8.8.8",
        "dnsserver2": "8.8.4.4"
      }
    

    然后可以使用viper.GetStringMap() 将其解析为map[string]string 结构,如下所示:map["dnsserver1":"8.8.8.8" "dnsserver2":"8.8.4.4"]。 然后,您可以使用给定键访问地图,例如 map["dnsserver1"],它会为您提供一个包含“8.8.8.8”的字符串。

    【讨论】:

      猜你喜欢
      • 2014-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-23
      • 2017-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多