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


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

查看所有标签

猜你喜欢:

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

Head First Web Design

Head First Web Design

Ethan Watrall、Jeff Siarto / O’Reilly Media, Inc. / 2009-01-02 / USD 49.99

Want to know how to make your pages look beautiful, communicate your message effectively, guide visitors through your website with ease, and get everything approved by the accessibility and usability ......一起来看看 《Head First Web Design》 这本书的介绍吧!

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

在线图片转Base64编码工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具