zoukankan      html  css  js  c++  java
  • golang validate构建

    验证规则:https://github.com/go-playground/validator

    中文参考:https://www.cnblogs.com/zj420255586/p/13542395.html

    https://www.cnblogs.com/wangkun122/articles/11023964.html

    验证器构建

    package validate_1
    
    import (
        "errors"
        "github.com/go-playground/locales/en"
        "github.com/go-playground/locales/zh"
        ut "github.com/go-playground/universal-translator"
        "gopkg.in/go-playground/validator.v9"
        entranslations "gopkg.in/go-playground/validator.v9/translations/en"
        zhtranslations "gopkg.in/go-playground/validator.v9/translations/zh"
        "reflect"
        "unicode/utf8"
    )
    
    /*
    https://www.jianshu.com/p/9ef19d5eac72
    构建验证器
    numeric:数字
    required :必填
    email_1:验证字符串是email格式;例:"email_1"
    url:这将验证字符串值包含有效的网址;例:"url"
    max:字符串最大长度;例:"max=20"
    min:字符串最小长度;例:"min=6"
    excludesall:不能包含特殊字符;例:"excludesall=0x2C"//注意这里用十六进制表示。
    len:字符长度必须等于n,或者数组、切片、map的len值为n,即包含的项目数;例:"len=6"
    eq:数字等于n,或者或者数组、切片、map的len值为n,即包含的项目数;例:"eq=6"
    ne:数字不等于n,或者或者数组、切片、map的len值不等于为n,即包含的项目数不为n,其和eq相反;例:"ne=6"
    gt:数字大于n,或者或者数组、切片、map的len值大于n,即包含的项目数大于n;例:"gt=6"
    gte:数字大于或等于n,或者或者数组、切片、map的len值大于或等于n,即包含的项目数大于或等于n;例:"gte=6"
    lt:数字小于n,或者或者数组、切片、map的len值小于n,即包含的项目数小于n;例:"lt=6"
    lte:数字小于或等于n,或者或者数组、切片、map的len值小于或等于n,即包含的项目数小于或等于n;例:"lte=6"
    
    跨字段验证
     eqfield=Field: 必须等于 Field 的值;
    nefield=Field: 必须不等于 Field 的值;
    gtfield=Field: 必须大于 Field 的值;
    gtefield=Field: 必须大于等于 Field 的值;
    ltfield=Field: 必须小于 Field 的值;
    ltefield=Field: 必须小于等于 Field 的值;
    eqcsfield=Other.Field: 必须等于 struct Other 中 Field 的值;
    necsfield=Other.Field: 必须不等于 struct Other 中 Field 的值;
    gtcsfield=Other.Field: 必须大于 struct Other 中 Field 的值;
    gtecsfield=Other.Field: 必须大于等于 struct Other 中 Field 的值;
    ltcsfield=Other.Field: 必须小于 struct Other 中 Field 的值;
    ltecsfield=Other.Field: 必须小于等于 struct Other 中 Field 的值;
    
    
    */
    
    type UserInfo struct {
        Name      string `json:"name" validate:"checkName" label:"姓名" checkName_err:"姓名长度不能大于5"` //声明自定义tag,函数必须定义,必须绑定
        FirstName string `json:"first_name" validate:"required" label:""`
        LastName  string `json:"last_name" validate:"required" label:""`
        Age       uint8  `json:"age" validate:"gte=0,lte=100" label:"年龄"`
        Email     string `json:"email_1" validate:"required,email" label:"邮箱"`
    }
    
    // 自定义验证函数
    func checkName(fl validator.FieldLevel) bool {
        count := utf8.RuneCountInString(fl.Field().String())
        if count > 5 {
            return false
        }
        return true
    }
    
    //func main() {
    //    user := UserInfo{
    //        Name:      "rosers",
    //        FirstName: "Badger",
    //        LastName:  "Smith",
    //        Age:       105,
    //        Email:     "",
    //    }
    //    c := make(map[string]validator.Func, 0)
    //    c["checkName"] = checkName
    //    res := autoValidate(user, "zh", c)
    //    //res := autoValidate(user, map[string]validator.Func{}, "zh")
    //    fmt.Println("res=", res)
    //}
    
    //通用验证器
    func AutoValidate(s interface{}, language string, customValidate map[string]validator.Func) []string {
        errs := make([]string, 0)
        //验证器
        validate := validator.New()
        //注册字段翻译
        if language != "en" {
            validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
                name := fld.Tag.Get("label")
                return name
            })
        }
    
        if customValidate != nil {
            //注册自定义规则
            for k, v := range customValidate {
                err := validate.RegisterValidation(k, v)
                if err != nil {
                    panic(err)
                }
            }
    
        }
    
        //语言切换
        var trans ut.Translator
        var err1 error
        switch language {
        case "en":
            trans, _ = ut.New(en.New()).GetTranslator(language)
            err1 = entranslations.RegisterDefaultTranslations(validate, trans)
        case "zh":
            trans, _ = ut.New(zh.New()).GetTranslator(language)
            err1 = zhtranslations.RegisterDefaultTranslations(validate, trans)
        default:
            err1 = errors.New("语言不存在")
        }
        if err1 != nil {
            panic(err1)
        }
        if customValidate != nil {
            //获取reflect.Type 类型
            typ := reflect.TypeOf(s)
            //获取reflect.Value 类型
            val := reflect.ValueOf(s)
            //获取到a对应的类别
            kd := val.Kind()
            //如果传入的不是struct,就退出
            if kd != reflect.Struct {
                panic("expect struct")
            }
    
            //获取到该结构体有几个字段
            num := val.NumField()
            //注册自定义规则
            for k, _ := range customValidate {
                //变量结构体的所有字段
                for i := 0; i < num; i++ {
                    //获取到struct标签, 注意需要通过reflect.Type来获取tag标签的值
                    tagVal := typ.Field(i).Tag.Get(k + "_err")
                    //如果该字段于tag标签就显示,否则就不显示
                    if tagVal != "" {
                        //注册自定义函数返回信息
                        validate.RegisterTranslation(k, trans, func(ut ut.Translator) error {
                            return ut.Add(k, tagVal, true)
                        }, func(ut ut.Translator, fe validator.FieldError) string {
                            t, _ := ut.T(k, fe.Field(), fe.Field())
                            return t
                        })
                    }
                }
            }
        }
    
        err := validate.Struct(s)
        if err != nil {
            for _, err := range err.(validator.ValidationErrors) {
                errs = append(errs, err.Translate(trans))
            }
        }
    
        return errs
    }
    View Code

    gin构建验证

    package ginvalidate
    
    import (
        "fmt"
        "github.com/gin-gonic/gin"
        "github.com/gin-gonic/gin/binding"
        "github.com/go-playground/locales/zh"
        ut "github.com/go-playground/universal-translator"
        "github.com/go-playground/validator/v10"
        zh_translations "github.com/go-playground/validator/v10/translations/zh"
        "reflect"
    )
    
    func init() {
        AutoValidate(nil)
    }
    
    var trans ut.Translator
    
    type AutoRule struct {
        Func     validator.Func `json:"func"`
        FuncName string         `json:"func_name"`
        ErrMsg   string         `json:"err_msg"`
    }
    
    func AutoValidate(customValidate []AutoRule) {
    
        uni := ut.New(zh.New())
        trans, _ = uni.GetTranslator("zh")
    
        if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
            //注册翻译器
            _ = zh_translations.RegisterDefaultTranslations(v, trans)
    
            //注册自定义函数
            for _, autoRule := range customValidate {
                _ = v.RegisterValidation(autoRule.FuncName, autoRule.Func)
                //根据提供的标记注册翻译
                v.RegisterTranslation(autoRule.FuncName, trans, func(ut ut.Translator) error {
                    return ut.Add(autoRule.FuncName, autoRule.ErrMsg, true)
                }, func(ut ut.Translator, fe validator.FieldError) string {
                    t, _ := ut.T(autoRule.FuncName)
                    return t
                })
            }
            //注册一个函数,获取struct tag里自定义的json作为字段名
            v.RegisterTagNameFunc(func(fld reflect.StructField) string {
                name := fld.Tag.Get("json")
                return name
            })
        }
    }
    
    //翻译输出错误
    func ValidateErrs(err error) map[string]string {
        //对验证结果进行翻译
        dumpErrs := make(map[string]string, 0)
        errs := err.(validator.ValidationErrors)
        for _, e := range errs {
            dumpErrs[e.Field()] = e.Translate(trans)
        }
        return dumpErrs
    }
    
    func ValidateBind(c *gin.Context, obj interface{}) map[string]string {
        fmt.Printf("T=%T,v=%v
    ", obj, obj)
        //对验证结果进行翻译
        err := c.ShouldBindJSON(obj)
        errs1 := make(map[string]string, 0)
        if err == nil {
            return errs1
        }
        //翻译
        errs := err.(validator.ValidationErrors)
        for _, e := range errs {
            errs1[e.Field()] = e.Translate(trans)
        }
        return errs1
    }
    
    //单条错误
    func ValidateErr(err error) string {
        if err == nil {
            return ""
        }
        errs := err.(validator.ValidationErrors)
        for _, e := range errs {
            return e.Translate(trans)
        }
        return ""
    }
    View Code

    自定义使用

    package main
    
    import (
        "fmt"
        "github.com/gin-gonic/gin"
        "github.com/go-playground/validator/v10"
        "go_code/pack/gin_validate/ginvalidate"
        "net/http"
        "time"
    )
    
    // 绑定为json 验证
    //binding有与validate相似的验证效果
    type Login struct {
        User     string    `json:"user"   binding:"required,max=10,min=5"label:"用户名"`
        Password string    `json:"password"  binding:"required"label:"密码"`
        CheckIn  time.Time `json:"check_in" binding:"required" label:"输入时间"`
    }
    
    func main() {
        router := gin.Default()
        // Example for binding JSON ({"user": "manu", "password": "123"})
        //注册路由
        router.POST("/loginJSON", login)
        // Listen and serve on 0.0.0.0:8080
        router.Run(":8088")
    }
    
    func login(c *gin.Context) {
        fmt.Println(123)
        //自定义
        //c1 := make(map[string]validator.Func, 0)
        //c1["密码长度不正确"] = passrule
        //s1 := []ginvalidate.AutoRule{ginvalidate.AutoRule{
        //    Func:     passrule,
        //    FuncName: "passrule",
        //    ErrMsg:   "密码长度不能小于5",
        //}}
        //ginvalidate.AutoValidate(s1)
        var json Login
        err := c.ShouldBindJSON(&json)
        errs := ginvalidate.ValidateErrs(err)
        //errs := ginvalidate.ValidateBind(c, json)
        fmt.Println(errs)
        if len(errs) != 0 {
            c.JSON(http.StatusBadRequest, errs)
            return
        }
        c.JSON(http.StatusOK, json)
        return
    
    }
    func passrule(fl validator.FieldLevel) bool {
        str := fl.Field().String()
        if len(str) < 5 {
            return false
        }
        return true
    }
    
    //func bookableDate(fl validator.FieldLevel) bool {
    //    date, ok := fl.Field().Interface().(time.Time)
    //
    //    if ok {
    //        today := time.Now()
    //        if today.After(date) {
    //            return false
    //        }
    //    }
    //    return true
    //}
    View Code
  • 相关阅读:
    DapperExtensions 使用教程
    C#事件订阅及触发例子
    01、类与结构的区别
    内网信息搜集
    Anydesk拿下远程桌面
    C++对注册表的操作
    Linux下常见流编辑器的使用
    Typecho1.1反序列化漏洞复现
    Nmap脚本编写
    Github学习
  • 原文地址:https://www.cnblogs.com/huay/p/13230558.html
Copyright © 2011-2022 走看看