如何在go中实现分段配置文件验证

时间:2018-04-11 16:45:55

标签: go

我尝试通过配置文件(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))。有什么想法或提示吗?

1 个答案:

答案 0 :(得分:1)

我建议您从c.Webserver.Validate()拨打c.Validate()

这样做的缺点是,每次添加新配置时都需要更新c.Validate(),这可能很容易忘记。但是,它“简单,易读且明确”(引自您的评论)。

或者,您可以循环遍历配置的每个元素,以查看哪些与Validater接口匹配,然后在其上调用Validate。但是,这将更加复杂,更难以理解。调试。除非绝对必要,否则通常建议避免反思。