使用Golang Viper读取地图片段

jax*_*orm 2 go

我正在从这里使用出色的毒蛇库:https : //github.com/spf13/viper

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

interval = 10
statsd_prefix = "pinger"



group "dns" {
  target_prefix = "ping"
  target "dns" {
    hosts = [
      "dnsserver1",
      "dnsserver2"
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

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

当我在使用中阅读它时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"
        }
       }
      }
     }
    }
   }
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Uve*_*tel 7

建议不要先描述您想要的配置结构,而不是先调用原始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"`
}
Run Code Online (Sandbox Code Playgroud)

并且比其中解组(解码)

var C config

err := viper.Unmarshal(&C)
if err != nil {
    t.Fatalf("unable to decode into struct, %v", err)
}
Run Code Online (Sandbox Code Playgroud)

假设解码器足够聪明,可以在可能的情况下取消所提供的结构。


小智 5

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

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

hosts = [
      "dnsserver1",
      "dnsserver2"
    ]
Run Code Online (Sandbox Code Playgroud)

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

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

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

"hosts": {
    "dnsserver1": "8.8.8.8",
    "dnsserver2": "8.8.4.4"
  }
Run Code Online (Sandbox Code Playgroud)

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