Go Gin框架的验证器
大约 3 分钟
Go Gin框架的验证器
众所周知,在 web 开发中参数校验是非常重要的一个环节,今天就来看看 gin 框架的验证器是如何使用的吧。
一、从最简单的示例开始
package main
import "github.com/gin-gonic/gin"
type UserReq struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
engine := gin.Default()
engine.POST("user", func(ctx *gin.Context) {
var req UserReq
if err := ctx.ShouldBindJSON(&req); err != nil {
fmt.Println(err)
}
// ... 业务逻辑
})
engine.Run(":8080")
}
那么我们需要如何去校验参数呢?
其实 gin 默认内置了验证器,我们只需要在结构体中加入对应的 tag 即可。
// 简单修改结构体如下
type UserReq struct {
Name string `json:"name" binding:"required"`
Age int `json:"age" binding:"required,max=200"`
}
我们传一个空参数调用该接口,查看打印结果看看吧
# 请求示例
curl -X POST http://localhost:8090/user -H "Content-Type: application/json" -d '{"name": ""}'
# 运行结果
Key: 'UserReq.Name' Error:Field validation for 'Name' failed on the 'required' tag
Key: 'UserReq.Age' Error:Field validation for 'Age' failed on the 'required' tag
可以看到已经产生了校验的效果了。
小总结: gin 默认使用 binding 这个关键字进行绑定校验的。内置了许多像:required 这样的关键字。
二、提示信息优化
虽然说已经产生了验证的效果,但是提示的内容并不符合国内用户的阅读习惯,系统大多数都是给普通用户使用的,所以需要更适合中国宝宝的提示语。
gin 的验证器已经考虑到了这一点,给我们提供了翻译工具。
go get github.com/go-playground/validator/v10
// 定义一个全局翻译器
var trans ut.Translator
// InitTrans 初始化翻译器
func InitTrans() error {
zh := zh.New()
uni := ut.New(zh, zh)
trans, _ = uni.GetTranslator("zh")
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
err := zhtranslations.RegisterDefaultTranslations(v, trans)
if err != nil {
return err
}
}
return nil
}
接口处修改为:
engine.POST("user", func(ctx *gin.Context) {
var req UserReq
if err := ctx.ShouldBindJSON(&req); err != nil {
errors, ok := err.(validator.ValidationErrors)
if ok {
fmt.Println(errors.Translate(trans))
} else {
fmt.Println(err.Error())
}
}
// ... 业务逻辑
})
完善代码后,此时我们再运行看看效果如何呢
map[UserReq.Age:Age为必填字段 UserReq.Name:Name为必填字段]
可以看到提示已经转化为中文了
思考: 虽然已经转化为中文了,但是效果也是不敬人意的,如何做到我们像要的结果呢?快去试试吧。
三、自定义验证规则
我们看到对于简单的 required 这样的验证已经达到了效果,但是在实际项目中可能存在很多自定义的验证规则,gin 是如何满足的呢?
直接看一个示例:
// 自定义一个手机号码的验证
v.RegisterValidation("isMobile", func(fl validator.FieldLevel) bool {
phone := fl.Field().String()
regex := `^1[3-9]\d{9}$`
re := regexp.MustCompile(regex)
return re.MatchString(phone)
})
v.RegisterTranslation("isMobile", trans, func(ut ut.Translator) error {
return ut.Add("isMobile", `不是一个有效的`, true)
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("isMobile", fe.Field())
return t
})
这段代码写在翻译器中即可, 要使用的话就在 tag 里加入 isMobile 就行
四、参考资料
更多使用方法及技巧可以去看看官方的资料