验证通常是所有编程语言中最常见的问题之一。
在我开始在Golang中解释如何进行惯用的方法之前...让我简要解释为什么我首先潜入其中。
在使用大量微服务的项目工作时,
需要维护每个人的构建时间配置。
这也意味着验证这些配置。否则,微服务将有运行时故障的风险! ðÖ
因此,假设我们在config.json
中具有以下配置
{
"server_url": "https://some-server-url",
"app_port": 8080
}
然后可以将其封装在Golang结构中:
type Config struct {
ServerUrl string `json:"server_url"`
AppPort int `json:"app_port"`
}
我们将config.json加载到结构:
func LoadConfig() (*Config, error) {
configFile, err := os.Open("configuration/config.json")
if err != nil {
log.Fatal("Could not open config file : ", err.Error())
}
decoder := json.NewDecoder(configFile)
config := Config{}
decodeErr := decoder.Decode(&config)
if decodeErr != nil {
log.Fatal("Could not decode config file : ", decodeErr.Error())
}
if !Validate(config) {
return nil, errors.New("Invalid config !")
}
return &config, nil
}
现在,假设我们要验证:
- 服务器URL和端口是非空的
- 端口的值是数字,在8080和8085之间
现在,直截了当的方法是:
编写if-else
条件代码以验证每个代码。就像是:
func Validate(config Config) bool {
if config.ServerUrl == "" {
return false
}
if config.AppPort == 0 {
return false
}
if config.AppPort >= 8080 || config.AppPort <= 8085 {
return false
}
return true
}
这可能会对更多此类字段和验证感到非常混乱。是的! ðµð«
一定有更好的方法(否则该博客将不存在!)
做到这一点的清洁剂,惯用的方法是使用 struct验证
type Config struct {
ServerUrl string `json:"server_url" validate:"required"`
AppPort int `json:"app_port" validate:"required,numeric,gte=8080,lte=8085"`
}
声明性,更接近结构定义。那不是美丽!
现在,我们的验证功能看起来像这样:
func Validate(config Config) bool {
validate := validator.New()
err := validate.Struct(config)
if err != nil {
fmt.Println("Invalid config !", err.Error())
return false
}
return true
}
此外,我们可能会有更有意义的错误来指出失败的验证:
func Validate(config Config) bool {
validate := validator.New()
err := validate.Struct(config)
if err != nil {
fmt.Println("Invalid config !")
for _, validationErr := range err.(validator.ValidationErrors) {
fmt.Println(validationErr.StructNamespace() + " violated " + validationErr.Tag() + " validation.")
}
return false
}
return true
}
前往Awesome validator library获取更多此类标签...