Go 中间件 - validator 校验器
介绍
Validator
是一个 Go
的第三方库,用于对数据进行校验,返回一个 validator.ValidationErrors
error
的切片,在 Tag
中配置各自字段的约束进行校验。
依赖
# 最基础的依赖
go get -u github.com/go-playground/validator/v10
# 国际化
go get -u github.com/go-playground/locales
go get -u github.com/go-playground/universal-translator
# 中文语言包
go get -u github.com/go-playground/locales/zh
# 中文校验器工具 用于注册
go get -u github.com/go-playground/validator/v10/translations/zh
简单测试
下面这个是最基础的配置
func Test_Validator(t *testing.T) {
type User struct {
UserName string `json:"user_name" validate:"required"`
Password string `json:"password" validate:"required,min=6,max=20"`
}
u := &User{
Password: "123",
}
validate := validator.New()
if errs := validate.Struct(u); errs != nil {
for _, err := range errs.(validator.ValidationErrors) {
fmt.Println(err)
}
}
}
Key: 'User.UserName' Error:Field validation for 'UserName' failed on the 'required' tag
Key: 'User.Password' Error:Field validation for 'Password' failed on the 'min' tag
国际化
不是很明白这种模式,逻辑有点混乱,需要一个 RegisterDefaultTranslations
方法连接校验器和翻译器吗?
自己尝试画了一个图,不是很对,用于自己理解
注册时需要注意给包命名
import (
"fmt"
"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"
"testing"
)
func Test_Validator_Local(t *testing.T) {
type User struct {
UserName string `json:"user_name" validate:"required"`
Password string `json:"password" validate:"required,min=6,max=20"`
}
u := &User{
Password: "123",
}
uni := ut.New(zh.New())
zhTranslator, _ := uni.GetTranslator("zh")
//if !found {
// fmt.Println("zhTranslator not found.", found)
// return
//}
validate := validator.New()
if err := zh_translations.RegisterDefaultTranslations(validate, zhTranslator); err != nil {
fmt.Println(err)
}
if errs := validate.Struct(u); errs != nil {
for _, err := range errs.(validator.ValidationErrors) {
fmt.Println(err.Translate(zhTranslator))
}
}
}
UserName为必填字段
Password长度必须至少为6个字符
校验规则
更多的参考官方的:Baked-in Validations
Tag |
说明 | 示例 |
---|---|---|
required |
必填 | validate:"required" |
min |
最小值 | validate:"required,min=1" |
ip |
IP 格式 | validate:"ip" |
gt |
大于 | validate:"gt=3" |
gte |
大于等于 | validate:"gte=3" |
eqfield |
等于某个字段 | validate:"eqfiled=Password" |
在 gin
中使用
在 gin
中内置 validator
,但是使用的 Tag
名是 binding
package main
import (
"errors"
"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"
"strings"
)
type User struct {
Username string `json:"username" binding:"required,gte=3,lte=8"`
Password string `json:"password" binding:"required,gte=8,lte=16"`
Sex uint8 `json:"sex" binding:"required"`
Email string `json:"email" binding:"required,email"`
Age int `json:"age"`
}
var trans ut.Translator
func main() {
r := gin.Default()
if err := InitTrans(); err != nil {
fmt.Println(err)
return
}
r.POST("/signup.do", func(ctx *gin.Context) {
u := new(User)
if err := ctx.ShouldBindJSON(u); err != nil {
errs, ok := err.(validator.ValidationErrors)
var msg string = "param is error"
if ok {
msg = ""
for _, validateErr := range errs {
msg = fmt.Sprintf("%s,%s", msg, validateErr.Translate(trans))
}
}
ctx.JSON(200, msg)
} else {
ctx.JSON(200, "signup success")
}
})
r.Run(":9999")
}
func InitTrans() error {
if validate, ok := binding.Validator.Engine().(*validator.Validate); ok {
uni := ut.New(zh.New())
trans, _ = uni.GetTranslator("zh")
zh_translations.RegisterDefaultTranslations(validate, trans)
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
return nil
} else {
return errors.New("get gin Validator failed")
}
}
请求测试
-
第一组
{ "username":"xxcheng", "password":"12345678", "email":"www@qq" }
",sex为必填字段,email必须是一个有效的邮箱"
-
第二组
{ "username":"xxcheng", "password":"123456", "sex":2 }
",password长度必须至少为8个字符,email为必填字段"
参考链接
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。