gin请求数据校验
source link: https://studygolang.com/articles/28300
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
前言
最近优化 gin+vue的前后端分离项目 代码时候,发现代码中对请求数据的校验比较繁琐,于是想办法简化它。最终我发现了 go-playground/validator 开源库很好用。
优化前代码
代码如下:
发现每个方法都这样校验数据,很繁琐。
优化代码
这里使用 go-playground/validator 开源库来简化请求校验。
1.安装 go-playground/validator
# 使用 Go Modules go env -w GO111MODULE=on # 安装 go-playground/validator go get github.com/go-playground/validator/v10
注意:v10版本是使用Go Modules,运行 go get github.com/go-playground/validator/v10
前需要确保 GO111MODULE=on
,不然会报: cannot find package "github.com/go-playground/validator/v10"
2.实现 StructValidator
接口的两个方法
StructValidator
是需要实现的最基本的接口,作为验证引擎来确保请求的正确性。
type StructValidator interface { ValidateStruct(interface{}) error Engine() interface{} }
-
ValidateStruct
:如果接收到的类型是一个结构体或指向结构体的指针,则执行验证。 -
Engine
: 返回支持StructValidator
实现的底层验证引擎。
实现接口:
package validator import ( "reflect" "sync" "github.com/gin-gonic/gin/binding" "github.com/go-playground/validator/v10" ) type DefaultValidator struct { once sync.Once validate *validator.Validate } var _ binding.StructValidator = &DefaultValidator{} // ValidateStruct 如果接收到的类型是一个结构体或指向结构体的指针,则执行验证。 func (v *DefaultValidator) ValidateStruct(obj interface{}) error { if kindOfData(obj) == reflect.Struct { v.lazyinit() //如果传递不合规则的值,则返回InvalidValidationError,否则返回nil。 ///如果返回err != nil,可通过err.(validator.ValidationErrors)来访问错误数组。 if err := v.validate.Struct(obj); err != nil { return err } } return nil } // Engine 返回支持`StructValidator`实现的底层验证引擎 func (v *DefaultValidator) Engine() interface{} { v.lazyinit() return v.validate } func (v *DefaultValidator) lazyinit() { v.once.Do(func() { v.validate = validator.New() v.validate.SetTagName("validate") // //v8版本,v8版本使用"binding" // v.validate.SetTagName("binding") }) } func kindOfData(data interface{}) reflect.Kind { value := reflect.ValueOf(data) valueType := value.Kind() if valueType == reflect.Ptr { valueType = value.Elem().Kind() } return valueType }
3.使用该验证引擎
修改 model
,添加 validate
验证
type Article struct { ID int `gorm:"primary_key" json:"id"` State int `json:"state" validate:"min=0,max=1"` TagID int `json:"tag_id" validate:"gt=0"` Title string `json:"title" validate:"required"` Desc string `json:"desc" validate:"required"` Content string `json:"content" validate:"required"` CoverImageURL string `json:"cover_image_url"` CreatedBy string `json:"created_by" validate:"required"` ModifiedBy string `json:"modified_by"` }
最后,只需在 main
函数中添加这行代码:
package main import ( "github.com/gin-gonic/gin/binding" "github.com/bingjian-zhu/gin-vue-admin/common/validator" ) func main() { binding.Validator = new(validator.DefaultValidator) // regular gin logic }
以上,我们就完成了gin的数据请求校验了,接下来看下优化后的代码。
优化后代码
只需要正常使用 c.Bing(model)
就可以对请求的数据进行校验了,代码简化了许多。
常用校验规则介绍
type Test struct { ID int `validate:"required"` //数字确保不为0 Name string `validate:"required,min=1,max=8"` //字符串确保不为"",且长度 >=1 && <=8 (min=1,max=8等于gt=0,lt=9) Value string `validate:"required,gte=1,lte=8"` //字符串确保不为"",且长度 >=1 && <=8 Status int `validate:"min=1,max=10"` //最小为0,最大为10(min=0,max=10等于gt=0,lt=11) PhoneNumber string `validate:"required,len=11"` //不为""且长度为11 Time string `validate:"datetime=2006-01-02"` //必须如2006-01-02的datetime格式 Color string `validate:"oneof=red green"` //是能是red或者green Size int `validate:"oneof=37 39 41"` //是能是37或者39或者41 Email string `validate:"email"` //必须邮件格式 JSON string `validate:"json"` //必须json格式 URL string `validate:"url"` //必须url格式 UUID string `validate:"uuid"` //必须uuid格式 }
更多校验规则可以阅读 源码文档 。
总结
go-playground/validator 开源库把gin的请求校验简单化了,使得我们代码更简单易读。
以上只是对结构体做请求校验,对于非结构体的请求校验,用老办法
import "github.com/astaxie/beego/validation" func (a *Article) GetArticle(c *gin.Context) { id, _ := strconv.Atoi(c.Param("id")) valid := validation.Validation{} valid.Min(id, 1, "id").Message("ID必须大于0") var data *models.Article code := codes.InvalidParams if !valid.HasErrors() { data = a.Service.GetArticle(id) code = codes.SUCCESS } else { for _, err := range valid.Errors { a.Log.Info("err.key: %s, err.message: %s", err.Key, err.Message) } } RespData(c, http.StatusOK, code, data) }
源码地址:https://github.com/Bingjian-Zhu/gin-vue-admin
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK