最近自己也在用gin框架做项目,然后在群里也有人问关于,参数验证的问题,今天有时间正好研究一下。
gin版本 : v1.6.2
基本验证
-
定义参数绑定结构体
account_io.go
package controller type Register struct { Mobile uint `json:"mobile" binding:"required"` Password string `json:"password" binding:"required,gte=6"` }
-
将相求参数与结构体绑定
account.go
package controller import ( "fmt" "mid-anding/pkg" "github.com/gin-gonic/gin" ) type AccountController struct { } // Register 账户注册 func (ctl *AccountController) Register(c *gin.Context) { var ( err error req Register ) if err = pkg.ParseRequest(c, &req); err != nil { return } fmt.Printf("%+v\n", req) }
pkg.ParseRequest
这是对gin自带参数绑定的封装request.go
,具体代码如下package pkg func ParseRequest(c *gin.Context, request interface{}) error { err := c.ShouldBind(request) if err != nil { c.JSON(200, app.Resp{ Code: 10004, Msg: err.Error(), }) return err } return nil }
OK,第一阶段的验证算是完成了,具体的验证参数可以查看package validator
自定义验证函数
-
定义验证函数
define.go
package vali import ( "strconv" "strings" "github.com/gin-gonic/gin/binding" "github.com/go-playground/validator/v10" ) var v *validator.Validate var trans ut.Translator func InitVali() { v, ok := binding.Validator.Engine().(*validator.Validate) if ok { // 自定义验证方法 v.RegisterValidation("checkMobile", checkMobile) } } func checkMobile(fl validator.FieldLevel) bool { mobile := strconv.Itoa(int(fl.Field().Uint())) re := `^1[3456789]\d{9}$` r := regexp.MustCompile(re) return r.MatchString(mobile) }
-
加载,在
main.go
中进行加载vali.InitVali() // 字段验证
-
准备工作完成,接下来让我们来使用他
package controller type Register struct { Mobile uint `json:"mobile" binding:"required,checkMobile"` Password string `json:"password" binding:"required,gte=6"` }
这个阶段已经完成,我们可以满足我们常见的参数验证场景了,但是还不够完美,哪里不够完美呢,提示信息,现在我们看到的提示信息是英文的,身为一个中国人,我们当然要提示中文才显得更加友好,所以接下来我们做汉化展示。
阶段补充-自定义错误信息
-
修改
define.go
并在v.RegisterValidation
下一行,加入以下代码v.RegisterTranslation("checkMobile", trans, func(ut ut.Translator) error { return ut.Add("checkMobile", "{0}长度不等于11位或{1}格式错误!", true) // see universal-translator for details }, func(ut ut.Translator, fe validator.FieldError) string { t, _ := ut.T("checkMobile", fe.Field(), fe.Field()) return t })
错误提示信息汉化
-
改造完
defind.go
如下package vali import ( "strconv" "strings" "github.com/gin-gonic/gin/binding" zhongwen "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" ) var v *validator.Validate var trans ut.Translator func InitVali() { // 中文翻译 zh := zhongwen.New() uni := ut.New(zh, zh) trans, _ = uni.GetTranslator("zh") v, ok := binding.Validator.Engine().(*validator.Validate) if ok { // 验证器注册翻译器 zh_translations.RegisterDefaultTranslations(v, trans) // 自定义验证方法 v.RegisterValidation("checkMobile", checkMobile) } } func Translate(errs validator.ValidationErrors) string { var errList []string for _, e := range errs { // can translate each error one at a time. errList = append(errList, e.Translate(trans)) } return strings.Join(errList, "|") } func checkMobile(fl validator.FieldLevel) bool { mobile := strconv.Itoa(int(fl.Field().Uint())) if len(mobile) != 11 { return false } return true }
-
改造
request.go
,代码如下package pkg import ( "mid-anding/pkg/vali" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "github.com/go-playground/validator/v10" ) func ParseRequest(c *gin.Context, request interface{}) error { err := c.ShouldBind(request) var errStr string if err != nil { switch err.(type) { case validator.ValidationErrors: errStr = vali.Translate(err.(validator.ValidationErrors)) case *json.UnmarshalTypeError: unmarshalTypeError := err.(*json.UnmarshalTypeError) errStr = fmt.Errorf("%s 类型错误,期望类型 %s", unmarshalTypeError.Field, unmarshalTypeError.Type.String()).Error() default: errStr = errors.New("unknown error.").Error() } logging.Error(err) app.RespData(c, e.PARAMS_IS_INVALID, errStr, nil) return err } return nil }
至此,工作结束,我们可以愉快的使用gin
自带的参数绑定验证了。
有疑问加站长微信联系(非本文作者)