【发布时间】:2019-09-26 17:01:52
【问题描述】:
我有一个像下面这样的 YAML。
connections:
- name: demo
hosts:
- demo.example.com:9200
username: admin
password: password
ssl: true
ssl_verify: true
version: 7
- name: test
hosts:
- "test.example.com:9200"
username: admin
password: password
如您所见,ssl 和 ssl_verify 未在列表的第二项中设置。我希望它们默认为true,但是,它没有发生。我尝试了不同的解决方案。
- Viper 默认设置 - 不起作用。
viper.SetDefault("connections[].ssl", "true")
type Config struct {
Connections []struct {
Name string
Hosts []string
Username string
Password string
Ssl bool `default:"true"`
SslVerify bool `default:"true"`
Version int
}
}
...
err := defaults.Set(config)
-
手动循环遍历结构列表。虽然这些方法适用于字符串,但它不适用于布尔值,因为它们在解组后已经用
false进行了初始化,我们不确定用户是否输入了false。 使用带有布尔值的指针。这是因为未初始化的值等于
nil,它们很容易被捕获。但是,在使用 config struct 时需要取消引用指针,这不是很方便。或者,可以基于来自解组的结构生成新结构。
type Config struct {
Connections []struct {
Name string
Hosts []string
Username string
Password string
Ssl *bool
SslVerify *bool
Version int
}
}
- 使用 hashmap 代替结构。这是可行的,因为没有初始化空值,但是,它需要在访问映射元素之前对它们进行检查,或者将映射转换为结构。
解决方案 4 和 5 可能会起作用,但我想知道是否有比这更好的方法。
有什么想法吗?
【问题讨论】:
-
你试过
viper.SetDefault("connections.ssl", true)吗?即没有[]并传入一个实际的布尔值而不是字符串。 -
是的,它不起作用。如果连接不是数组,它仅适用于结构,但这不是我需要的。
-
问题似乎是在解组之前您不知道 Connections 集合中有多少元素,因此没有一种使用默认值初始化切片的好方法。您是否可以控制
Config结构本身的定义?在这种情况下,将属性重命名为NoSsl和NoSslVerify可能是重新构建事物的好方法。 -
您可以先将其加载为 hashmap,填补空白,转储(到文件或字符串),然后使用适当的类型重新加载。这样您就不必在剩余的运行时间进行检查。