gin请求数据校验

栏目: IT技术 · 发布时间: 4年前

内容简介:最近优化代码如下:

前言

最近优化 gin+vue的前后端分离项目 代码时候,发现代码中对请求数据的校验比较繁琐,于是想办法简化它。最终我发现了 go-playground/validator 开源库很好用。

优化前代码

代码如下:

gin请求数据校验

发现每个方法都这样校验数据,很繁琐。

优化代码

这里使用 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的数据请求校验了,接下来看下优化后的代码。

优化后代码

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


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

网络素养

网络素养

[美]霍华德·莱茵戈德 / 张子凌、老卡 / 译言·东西文库/电子工业出版社 / 2013-8-1 / 49.80元

有人说Google让我们变得更笨,有人说Facebook出卖了我们的隐私,有人说Twitter将我们的注意力碎片化。在你担忧这些社会化媒体让我们变得“浅薄”的时候,有没问过自己,是否真正地掌握了使用社会化媒体的方式? 这本书将介绍五种正在改变我 们这个世界的素养:注意力、 对垃圾信息的识别能力、参与力、协作力和联网智慧。当有足够多的人学会并且能够熟练的使用这些技术,成为真正的数字公民后。健康......一起来看看 《网络素养》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换