Gin: 数据校验
validator
标签
语法介绍
gin框架依赖于validator,validator是基于结构体标签和反射进行数据校验的框架validator提供的结构体标签是validate:1
2
3type A struct {
Pub string `validate:"endwith=abc"`
}validator提供的标签在baked_in.go中标签的不同规则通过
,相与,通过|相或,标签的参数通过=传递,oneof标签的不同参数通过空格分隔,-表示跳过验证,特殊字符(-、,、=、|)需要unicode转义1
2
3
4
5
6type A struct {
Pub string `validate:"requried,min=3,max=8"`
Enum string `validate:"required,oneof=admin rdonly user"`
Abc string `validate:"required,eq=abc0x3d"`
Ignore int `validate:"-"`
}=为0x3d,,为0x2c,|为0x7c,-为0x2d与和或不支持使用括号,只能从左到右校验
通用校验
eq/lt/gt/ne/lte/gte=xxx:等于/小于/大于/不等于/小于等于/大于等于校验required:强制要求- 数值/布尔值:允许为零值
- 结构体/字符串:禁止为空结构体/空串
- 不允许为
nil
min/max:限制数值范围omitempty:可选字段,即可以是nil或零值,如果不为nil则要经过后续的校验omitnil:可选字段,可以是nil,但如果是零值则要经过后续校验oneof=xxx1 xxx2:限制可选值范围,可用于枚举len=xxx:限制长度required_if=Field xxx:Field为xxx时强制要求unique:不允许重复
常用格式校验
email:是否为邮箱格式uuid/uuid4:uuid/uuid4校验json:json格式校验datetime=DateTimeFormat:日期时间验证base64:base64格式校验
常用字符串校验
alphanum/alpha/numeric:是否只包含数字字母/字母/数字contains=xxx:是否包含xxx子串containsany=xxx:是否包含xxx字符集中的任何字符excludes=xxx:是否不包含xxx子串excludesall=xxx:是否不包含xxx字符集中的任何字符startswith=xxx/startsnotwith=xxx:是否以/不以指定文本开始endswith=xxx/endsnotwith=xxx:是否以/不以指定文本结束uppercase/lowercase:是否全大写/小写
常用跨字段校验
validator比起java的bean validation,还支持跨字段验证eqfield/nefield=OtherField:本字段和指定字段相等/不相等gtfield/gtefield/ltfield/ltefield=OtherField:大于/大于等于/小于//小于等于指定字段csfield系列可以跨结构体校验,但是不常用
常用网络字段校验
ip/ipv4/ipv6:通用ip/ipv4/ipv6地址格式校验url/uri:url/uri格式校验hostname:主机名校验fqdn:完全限定域名校验
验证API
创建验证器
- 使用
validator.New() *validator.Validate创建验证器 - 通常使验证器为单例模式
结构体校验
*Validate.Struct(any) error:验证传入的结构体的所有公开字段,即首字母大写的字段,默认进行递归校验应该传入结构体指针,否则返回
InvalidValidationError如果验证出错,将返回
ValidationErrors,被封装成error提取校验错误:
1
2
3err := validate.Struct(a)
for _, err := range err.(validator.ValidationErrors) {
}其中
err即validator.FieldErrorFieldError提供若干方法:
其它数据结构的校验
虽然通常用于结构体,但也可以用于其它数据结构体的校验
map对象:使用一个和map对象结构相同的map对象,其中每个键对应的值是标签数据通过
*Validate.ValidateMap(data, rules) map[string]any校验,返回错误map,每个键对应一个FieldError切片:通过
*Validate.Var(any, tag string)校验,从左到右维度下降(切片本身到切片的每个元素),通过dive标签划分不同的维度多维切片道理类似,通过
dive标签划分不同维度一般变量:同样通过
Var()进行验证
自定义标签
自定义别名
*Validate.RegisterAlias(alias, tag string):将一个tag命名为alias,则验证时会直接展开成tag
自定义验证函数
RegisterValidation(tag string, fn Func, callValidationEvenIfNull ...bool) error:通过注册函数注册Func是一个函数,签名为func(fl FieldLevel) bool,其中FieldLevel接口是一系列返回reflect.Value的快捷函数,最常用的是Filed()和Param(),表示获取当前字段的值和标签参数fn返回true表示校验成功
与Gin的集成
- 在
gin中,标签使用binding而不是validate - 在
gin中,不需要显式创建验证器和显式调用验证方法,所有校验错误会在解析数据、绑定数据失败时返回error