我正在编写守护程序的配置处理程序,并利用yaml
软件包来完成。导入文件的方式如下:
package daemon
import (
"ioutil"
"log"
"gopkg.in/yaml.v2"
)
type daemonConfig struct {
BindAddress string `yaml:"bind_address"`
BindPort int `yaml:"bind_port"`
VerifySSL bool `yaml:"verify_ssl"`
}
我很容易从YAML文件中解组数据,如下所示:
func (config *daemonConfig) getConf() *daemonConfig {
yamlFile, err := ioutil.ReadFile("config.yaml")
if err != nil {
log.Fatal("Unable to open config.yaml:", err)
}
err = yaml.Unmarshal(yamlFile, config)
if err != nil {
log.Fatal("Failed to unmarshall config.yaml:", err)
}
config, err = setDefaults(config)
return config
}
我的问题是关于我的自定义setDefaults函数。如果没有提供bind_port
或bind_address
之类的字段,我想将它们设置为默认值:
func setDefaults(config *daemonConfig) (*daemonConfig, error) {
if len(config.BindAddress) <= 0 {
config.BindAddress = "0.0.0.0"
}
if config.BindPort == 0 {
config.BindPort = 9999
}
return config, nil
}
您会注意到我没有将默认设置为verify_ssl
;当yaml
取消编组并且找不到该字段时,它将bool
初始化为false
,这与我希望默认行为恰好相反。我希望用户将SSL验证显式设置为关闭,而不是在未指定的情况下默认将其关闭。如果我的config.yaml
完全为空,并且希望设置默认值,它将始终将verify_ssl
设置为false(此日志来自应用程序的其他位置):
2019/02/19 03:56:08 Currently loaded config: {0.0.0.0 9999 false}
如果正在解组的YAML字段中不存在该字段,我将如何检查该行是否存在?我可以手动读取文件并首先检查该参数,但是我想知道我是否拥有一种更优雅的方式。否则,我将只使用ioutil
和字符串检查来做到这一点。谢谢!
答案 0 :(得分:3)
感谢Thomas和mh-cbon,我发现我可以为此使用一个指针。如果我将VerifySSL
字段更改为使用指针并添加omitempty
:
type daemonConfig struct {
BindAddress string `yaml:"bind_address"`
BindPort int `yaml:"bind_port"`
VerifySSL *bool `yaml:"verify_ssl",omitempty`
}
我可以简单地取消引用结构中的字段以获取未编组的yaml
的真实值。设置默认值非常简单:
func setDefaults(config *daemonConfig) (*daemonConfig, error) {
if len(config.BindAddress) <= 0 {
config.BindAddress = "0.0.0.0"
}
if config.BindPort == 0 {
config.BindPort = 9999
}
if config.VerifySSL == nil {
ssl := true
config.VerifySSL = &ssl
}
return config, nil
}
如果它已加载到文件中,则config.VerifySSL
将包含bool
的地址,因此不会是nil
,并且如果它确实不在文件中,则该字段只是nil
,我可以设置它或通过指针获取它。
编辑:
请注意,如果您的VerifySSL
指针为nil,则不能这样分配:
*config.VerifySSL = true
那是取消引用nil
指针。我已经更新了解决方案,使其包含更多易于管理的内容。