gin框架使用goframe框架的gvalid数据校验组件

前言

gin框架自带了go-playground/validator这个数据校验组件,但对国内的使用习惯来说不太好用,还是国产goframe框架的gvalid数据校验组件更加适合中国宝宝。
看了一下goframe社区也有这方面的融合先驱,但用的方法是封装了一个方法,不太优雅。看了一下gin源码,他这块是用接口实现的,也就说是可以自定义校验方法的。

开干

1. 安装gin和gvalid

go get -u github.com/gin-gonic/gin
go get github.com/gogf/gf/v2/util/gvalid

2. 实现StructValidator接口

该接口位于binding/binding.go:53,gin框架自带的default_validator既使用go-playground/validator实现了这个接口。
代码如下:

package validator

import (
    "context"
    "github.com/gin-gonic/gin/binding"
    "github.com/gogf/gf/v2/util/gvalid"
    "reflect"
    "sync"
)

type GfValidator struct {
    once     sync.Once
    validate *gvalid.Validator
}

func (v *GfValidator) ValidateStruct(obj any) error {
    if obj == nil {
        return nil
    }

    value := reflect.ValueOf(obj)
    switch value.Kind() {
    case reflect.Ptr:
        return v.ValidateStruct(value.Elem().Interface())
    case reflect.Struct:
        return v.validateStruct(obj)
    case reflect.Slice, reflect.Array:
        // 这里如果多个错误,会一并返回,如果只需要第一个错误,稍微改造就可以
        count := value.Len()
        validateRet := make(binding.SliceValidationError, 0)
        for i := 0; i < count; i++ {
            if err := v.ValidateStruct(value.Index(i).Interface()); err != nil {
                validateRet = append(validateRet, err)
            }
        }
        if len(validateRet) == 0 {
            return nil
        }
        return validateRet
    default:
        return nil
    }
}

func (v *GfValidator) Engine() any {
    v.lazyInit()
    return v.validate
}

func (v *GfValidator) lazyInit() {
    v.once.Do(func() {
        v.validate = gvalid.New()
    })
}

func (v *GfValidator) validateStruct(obj any) error {
    v.lazyInit()
    return v.validate.Data(obj).Run(context.Background())
}

3. 绑定新的校验组件

binding.Validator = new(validator.GfValidator)

4. 完事儿,测试一下

package main

import (
    "gin-validator/internal/validator"
    "github.com/gin-gonic/gin"
    "github.com/gin-gonic/gin/binding"
    "net/http"
)

type BizReq struct {
    Account   string `v:"required#"`
    Password  string `v:"required|same:Password2"`
    Password2 string `v:"required"`
}

func main() {
    r := gin.Default()
    // 绑定新的校验组件
    binding.Validator = new(validator.GfValidator)
    // 弄个接口测试一下
    r.POST("/ping", func(c *gin.Context) {
        var req BizReq
        if err := c.ShouldBindJSON(&req); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // listen and serve on 0.0.0.0:8080
}

gin框架使用goframe框架的gvalid数据校验组件

老铁,没毛病,使用习惯和原生一样,但错误提示更加适合中国宝宝了
可能有老铁会问了,这又加载了gf框哒,会不会把项目搞大了呀,不用担心哈,go编译时按需编译的

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 2

go-playground/validator 这个包也有语言包,不过用起来确实不顺手,语言包翻译不太好用,想自定义又麻烦

1个月前 评论
Colorado (楼主) 1个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!