我尝试通过配置文件(yaml)配置CLI应用程序。该应用程序有几个“组件”(比如一个持久层,一个集成的Web服务器等)。这些组件在子包中进行管理,以保持代码整洁。这些组件的配置在其包中定义 并在配置包中“合并”到表示配置文件的结构。请将此代码视为演示实现:
package main
import (
"errors"
"fmt"
yaml "gopkg.in/yaml.v2"
)
//
// This would be in package 'webserver'
// Only the Config part is shown, there would be a constructor and the implementation of
// the webserver as well...
//
// WebserverConfig holds all required configuration params
type WebserverConfig struct {
Listen string `yaml:"listen"`
Autostart bool `yaml:"autostart"`
}
// Validate checks if all fields make sense and returns a list of error string if problems
// are found
func (wsc WebserverConfig) Validate() (error, []string) {
errs := []string{}
if wsc.Listen == "" {
errs = append(errs, "Field 'listen' must not be empty.")
}
if len(errs) > 0 {
err := errors.New("Config of 'webserver' has errors")
return err, errs
}
return nil, errs
}
// UnmarshalYAML implements a custom unmarshaller to make sure defaults are set
// to meaningful values
func (wsc *WebserverConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
type WebserverConfigDefaulted WebserverConfig
var defaults = WebserverConfigDefaulted{
Listen: ":8080",
Autostart: true,
}
out := defaults
err := unmarshal(&out)
*wsc = WebserverConfig(out)
return err
}
//
// This would be in package conf
//
//
// Config is the global configuration composed of all component configuration sections
type Config struct {
Webserver WebserverConfig `yaml:"webserver"`
}
// Load reads the bytes into the global config
func Load(data string) (Config, error) {
c := Config{}
err := yaml.Unmarshal([]byte(data), &c)
if err != nil {
return c, fmt.Errorf("Error while unmarshalling configuration from yaml: %s", err.Error())
}
return c, nil
}
// Validate should call each individual component configurations validate function (if it exists)
func (c Config) Validate() error {
// TODO: IMPLEMPNT...
return nil
}
//
// This is finally in main
//
//
var yamlFile = `---
webserver:
listen: ":9999"
`
func main() {
c, err := Load(yamlFile)
if err != nil {
fmt.Println(err)
}
err = c.Validate()
if err != nil {
fmt.Println(err)
}
}
在这里的操场上找到它(由于对于yaml的dep而没有运行):https://play.golang.org/p/i3EAZJP7aYz
问题:此时我不知道如何实现全局验证函数func (c Config) Validate() error
来调用'组件配置'的所有验证函数(例如func (wsc WebserverConfig) Validate() (error, []string)
)。有什么想法或提示吗?
答案 0 :(得分:1)
我建议您从c.Webserver.Validate()
拨打c.Validate()
。
这样做的缺点是,每次添加新配置时都需要更新c.Validate()
,这可能很容易忘记。但是,它“简单,易读且明确”(引自您的评论)。
或者,您可以循环遍历配置的每个元素,以查看哪些与Validater
接口匹配,然后在其上调用Validate
。但是,这将更加复杂,更难以理解。调试。除非绝对必要,否则通常建议避免反思。