进行自定义结构验证 - 惯用方式
#编程 #go #idiomatic #validation

在上一个博客中,我们使用validator library在Golang中进行了结构验证。继续,在此博客中,我们将介绍自定义验证。

假设以下结构:

type Config struct {
    ServerUrl string
    AppPort   int
}

我们可以使用图书馆提供的validations来验证我们的结构:

import (
    "fmt"
    "github.com/go-playground/validator"
    "strings"
)

func Validate(config Config) bool {
    validate := validator.New()
    validationErr := validate.Struct(config)
    if validationErr != nil {
        return false    
    }
    return true
}

现在进入自定义验证的主题

说,我们想检查ServerUrl字段是否为HTTPS URL
直截了当的方法是引入一个函数:

func customValidator(config Config) bool {
    value := config.ServerUrl
    if !strings.HasPrefix(value, "https://") {
        return false
    }
    return true
}

并记住在我们的Validate()funcðâ€

中调用它

,或者我们可以以惯用的方式做到这一点,并利用validator library

然后自定义验证功能看起来像:

import (
    "github.com/go-playground/validator"
    "strings"
)

func CustomValidation(fl validator.FieldLevel) bool {
    value := fl.Field().String()
    if !strings.HasPrefix(value, "https://") {
        return false
    }
    return true
}

“为什么这个怪异的功能签名?” ð您问 - 短暂地抓住这个问题...

下一步是向validator library注册我们的新规则。

import (
    "fmt"
    "github.com/go-playground/validator"
    "strings"
)

func Validate(config Config) bool {
    validate := validator.New()

    // Registering the new rule "is_https" ...
    err := validate.RegisterValidation("is_https", CustomValidation)
    if err != nil {
        fmt.Println("Error registering custom validation :", err.Error())
    }

    validationErr := validate.Struct(config)
    if validationErr != nil {
        return false    
    }
    return true
}

现在我们的规则已注册,让我们将tag附加到结构的字段:

type Config struct {
    // Careful, the tag name should be identical to the one registered
    ServerUrl string `validate:"is_https"`
    AppPort   int 
}

和voilã! ð我们完成了!

现在,回到CustomValidation()函数的怪异签名的问题 -

观察validate.RegisterValidation()接收:

  1. 您想如何参考结构中的验证。
  2. a validator.Func-本质上是类型的函数:func(fl FieldLevel) bool (reference source code)

甚至在结构级别的验证 - 涉及同一结构的多个字段的验证 - 可以通过相似的函数签名来实现:func(fl StructLevel) bool

这就是最终代码的样子:https://github.com/PankhudiB/go-config-validation/blob/main/configuration/custom_validation.go

愉快的编码! ð©ð»