You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gin基于go-playground/validator实现自定义IsValid接口校验逻辑

Gin 通用自定义IsValid校验器实现

核心实现逻辑

你只需要通过validator.FieldLevel提供的方法拿到当前字段的反射值,处理指针/值类型的边界情况后做接口断言即可。注意代码需要引入reflect标准库完成反射操作,补全后的校验注册代码如下:

import (
    "reflect"
    "github.com/gin-gonic/gin/binding"
    "github.com/go-playground/validator/v10"
)

// 全局定义通用IsValid接口
type IsValid interface {
    IsValid() bool
}

// 注册自定义校验逻辑
func init() {
    if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
        // validator默认会对标签名做小写归一化,这里注册名统一用全小写避免匹配歧义
        v.RegisterValidation("isvalid", func(fl validator.FieldLevel) bool {
            field := fl.Field()
            
            // 处理指针类型字段:如果是nil指针直接判定为校验不通过
            if field.Kind() == reflect.Ptr {
                if field.IsNil() {
                    return false
                }
                field = field.Elem()
            }

            // 先尝试直接断言:覆盖值类型实现接口、指针类型被Elem转成值类型的场景
            isValidInstance, ok := field.Interface().(IsValid)
            if ok {
                return isValidInstance.IsValid()
            }

            // 兼容值类型字段、IsValid方法为指针接收者的场景:如果字段可寻址,取地址后再断言
            if field.CanAddr() {
                isValidInstance, ok = field.Addr().Interface().(IsValid)
                if ok {
                    return isValidInstance.IsValid()
                }
            }

            // 字段未实现IsValid接口,校验不通过
            return false
        })
    }
}

使用注意事项

  • 结构体标签要和注册的校验名匹配,直接写binding:"isValid"或者binding:"isvalid"都可以,validator内部会自动转小写匹配,使用示例:
    // 示例:自定义手机号类型实现IsValid接口
    type Phone string
    func (p Phone) IsValid() bool {
        // 替换为实际业务校验逻辑,比如正则匹配手机号格式
        return len(p) == 11
    }
    
    // 请求结构体
    type UserReq struct {
        Name  string `json:"name" binding:"required"`
        Phone Phone  `json:"phone" binding:"required,isvalid"` // 加isvalid标签即可触发自定义校验
    }
    
  • 如果你的自定义类型用指针接收者实现IsValid()方法,结构体字段既可以声明为指针类型(比如Phone *Phone),也可以声明为值类型,上面的兼容逻辑已经处理了可寻址场景的断言问题,不需要额外修改。
  • 指针字段如果为nil,默认会判定为校验不通过,如果你有业务需求允许空指针跳过校验,可以把指针判空分支的return false改成return true即可。

内容的提问来源于stack exchange,提问作者Manuelarte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 04:09:24