1.安装validator

go get -u github.com/go-playground/validator/v10

2.使用

package main

import (
    "fmt"
    "github.com/go-playground/validator/v10"
    //"gopkg.in/go-playground/validator.v10"
    "net/http"
)

type User struct{
    UserName string `validate:"min=3,max=13"`
    Password string `validate:"min=3,max=13"`
}

func main() {
    u := User{UserName: "z"}
    validate := validator.New()

    fmt.Println(u)
    err := validate.Struct(u)
    fmt.Println("err:",err)
}

错误提示

{z }
err: Key: 'User.UserName' Error:Field validation for 'UserName' failed on the 'min' tag
Key: 'User.Password' Error:Field validation for 'Password' failed on the 'min' tag

3.校验规则

len:length 等于,长度相等
max:小于等于
min:大于等于
eq:等于,字符串相等
ne:不等于
gt:大于
gte:大于等于
lt:小于
lte:小于等于,例如lte=10;
oneof:值中的一个,例如oneof=1 2

支持时间范围的比较lte
时间 RegTime time.Time `validate:"lte"` 小于等于当前时间

跨字段约束
eqfield=ConfirmPassword
eqcsfield=InnerStructField.Field

字符串规则
contains=:包含参数子串
containsany:包含参数中任意的 UNICODE 字符
containsrune:包含参数表示的 rune 字符
excludes:不包含参数子串
excludesall:不包含参数中任意的 UNICODE 字符
excludesrune:不包含参数表示的 rune 字符
startswith:以参数子串为前缀
endswith:以参数子串为后缀

使用unqiue来指定唯一性约束,对不同类型的处理如下:

对于数组和切片,unique约束没有重复的元素;
对于map,unique约束没有重复的值;
对于元素类型为结构体的切片,unique约束结构体对象的某个字段不重复,通过unqiue=name

特殊规则

-:跳过该字段,不检验;
|:使用多个约束,只需要满足其中一个,例如rgb|rgba;
required:字段必须设置,不能为默认值;
omitempty:如果字段未设置,则忽略它。

4.自定义规则及自定义提示信息

package main

import (
    "fmt"
    "github.com/go-playground/validator/v10"
    "log"
    "reflect"
    //"gopkg.in/go-playground/validator.v10"
    "net/http"
)

type User struct{
    UserName string `validate:"minReg" reg_error_info:"用户名至少6个字符"`   //通过reg_error_info标签记录
    //reg_error_info也可以是标记错误的唯一标识,通过传入的local_language 从库中或者缓存中找到对应国家的错误提示信息
    Password string `validate:"minReg" reg_error_info:"密码至少6个字符"`
}

//自定义的校验规则,可以使用正则表达式进行匹配,这里仅仅使用了长度判断
func minRegFun(f validator.FieldLevel) bool {
    value := f.Field().String()
    log.Println(f)
    if len(value) < 6 {
        return false
    }else {
        return true
    }

}

func main() {
    u := User{UserName: "zzzzzz",Password: "xxxx"}
    validate := validator.New()
    validate.RegisterValidation("minReg", minRegFun)   //注册自定义的校验函数 minReg和validate tag值保持一致
    err := validate.Struct(u) //校验
    errorInfo := processErr(u, err)   //处理错误信息
    if len(errorInfo) != 0 {
        log.Println(errorInfo)
    } else {
        log.Println("校验通过")
    }
}

func processErr(u interface{},err error) string {
    if err == nil {  //如果为nil 说明校验通过
        return ""
    }

    invalid, ok := err.(*validator.InvalidValidationError)   //如果是输入参数无效,则直接返回输入参数错误
    if ok {
        return "输入参数错误:" + invalid.Error()
    }
    validationErrs := err.(validator.ValidationErrors)   //断言是ValidationErrors
    for _, validationErr := range validationErrs {
        fieldName := validationErr.Field()              //获取是哪个字段不符合格式
        field, ok := reflect.TypeOf(u).FieldByName(fieldName)  //通过反射获取filed
        if ok {
            errorInfo := field.Tag.Get("reg_error_info")  //获取field对应的reg_error_info tag值
            return fieldName + ":" + errorInfo  //返回错误
        }else {
            return "缺失reg_error_info"
        }
    }
    return ""
}

结果

校验通过

2021/08/03 10:10:15 Password:密码至少6个字符
03-05 22:29