Go validator
官方文档 Package validator
Github地址 Package validator
安装
使用 go get
go get github.com/go-playground/validator/v10
错误返回值
对于错误的验证输入,Validator 只返回 InvalidValidationError,nil 或 ValidationErrors 作为类型错误;因此,代码中,我们需要做的就是检查返回的错误是否为 nil,如果不是,检查错误是否为 InvalidValidationError(如果有必要,大多数情况下不需要),将其类型转换为 ValidationErrors 类型。如下所示:
err := validate.Struct(mystruct)
validationErrors := err.(validator.ValidationErrors)
使用
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
"test_validator/model"
)
type User struct {
Username string `validate:"min=2,max=6"`
Password string `validate:"min=6,max=10"`
}
func main() {
// 创建一个验证器
validate := validator.New()
u1 := model.User{
Username: "user",
Password: "2125",
}
err := validate.Struct(u1)
fmt.Println(err)
}
# 验证成功的返回消息
<nil>
# 验证失败的返回消息
Key: 'User.Username' Error:Field validation for 'Username' failed on the 'max' tag
Key: 'User.Password' Error:Field validation for 'Password' failed on the 'max' tag
注意:字符串长度和数值的范围都可以通过 min 和 max 来约束
常用约束
len
:等于,例如:len=10
;max
:小于等于,例如:max=10
;min
:大于等于,例如:min=10
;eq
:等于,注意与len
不同。对于字符串,eq
约束字符串本身的值,而len
约束字符串长度。例如:eq=10
;eq_ignore_case
:等于忽略大小写,例如:eq_ignore_case
;ne
:不等于,例如:ne=10
;ne_ignore_case
:不等于忽略大小写,例如:ne_ignore_case=10
;gt
:大于,例如:gt=10
;gte
:大于等于,例如:gte=10
;lt
:小于,例如:lt=10
;lte
:小于等于,例如:lte=10
;oneof
:只能是列举出的值其中一个,这些值必须是数值或字符串,以空格分隔,如果字符串中有空格,将字符串用单引号包围,例如:oneof=red green
;
字段约束和跨字段约束
validator 允许定义跨字段的约束,即该字段与其他字段之间的关系。而跨字段约束分为两种:一种是同一结构体的平级字段,另一种是其它结构体中的其它字段的字段。例如相等约束
(eq)
eqfield
:相等约束,在同一结构体中的字段eqcsfield
:相等约束,在不同结构体中的字段
具体示例代码如下:
type User struct {
Username string `validate:"min=2,max=6"`
Password string `validate:"min=6,max=10"`
Pass string `validate:"eqfield=Password"`
}
type Pass struct {
UserStructField User
Pass string `validate:"eqcsfield=UserStructField.Password"`
}
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
"test_validator/model"
)
func main() {
validate := validator.New()
u1 := model.User{
Username: "user",
Password: "123456",
Pass: "123456",
}
err := validate.Struct(u1)
fmt.Println(err)
u2 := model.Pass{
UserStructField: u1,
Pass: "123456",
}
err2 := validate.Struct(u2)
fmt.Println(err2)
}
contains
:包含参数,例如:contains=email
;containsany
:包含参数中任意的 UNICODE 字符,例如:containsany=abc123
;containsrune
:包含参数表示的 rune 字符,例如containsrune=☻
;excludes
:不包含参数,例如:excludes=email
;excludesall
:不包含参数中任意的 UNICODE 字符,例如:excludesall=abc123
;excludesrune
:不包含参数表示的 rune 字符,例如:excludesrune=☻
;startswith
:以参数为前缀,例如:startswith=hi
;endswith
:以参数为后缀,例如:endswith=bye
;unique
:指定唯一性约束- 对于切片和数组,
unique
约束没有重复的元素; - 对于map,
unique
约束没有重复的值; - 对于元素类型为结构体的切片,
unique
约束结构体对象的某个字段不重复,通过unique=field
指定这个字段名;
- 对于切片和数组,
分割约束
dive
标签用于在切片、数组和 map 中分割约束规则的层次级别,它还可以与 keys
、endkeys
标签配合使用
示例一
[][]string with validation tag "gt=0,dive,len=1,dive,required"
gt=0
将用于约束[]
,而len=1
将用于约束[]string
,required
将用于约束 string
示例二
[][]string with validation tag "gt=0,dive,dive,required"
gt=0
将用于约束[]
,[]stirng
将跳过约束,而required
用于约束string
。
keys 和 endkeys
keys
和 endkeys
搭配 dive
标签一起使用,作用于 map 数据类型,表示当前约束是针对 map 的 key 而不是 value。
示例一
map[string]string with validation tag "gt=0,dive,keys,eg=1|eq=2,endkeys,required"
gt=0
作用于 map 本身,eg=1|eq=2
作用于 map 的键,required
则是作用于 map 的值。
示例二
map[[2]string]string with validation tag "gt=0,dive,keys,dive,eq=1|eq=2,endkeys,required"
gt=0
将作用于 map 本身,eq=1|eq=2
将作用于 map 的键数组中的每一个值,即 [2]string
数组中的每一个值,required
则是作用于 map 的值。
特殊约束
-
:跳过该字段,不检验;|
:使用多个约束,只需要满足其中一个,例如:rgb|rgba
;required
:字段必须设置,不能为默认值;omitempty
:如果字段未设置,则忽略它;
自定义约束
type Register struct {
Username string `validate:"min=2,max=6"`
// 使用自定义约束
Password string `validate:"checkPassword"`
}
// 检查约束是否满足,可以通过 validator.FieldLevel 取出要检查的字段的信息
func CheckPassword(fl validator.FieldLevel) bool {
value := fl.Field()
if len(value.String()) > 5 {
return true
}
return false
}
func main() {
validate := validator.New()
// 调用 RegisterValidation() 方法将约束注册到指定的名字上
validate.RegisterValidation("checkPassword", model.CheckPassword)
register := model.Register{
Username: "user",
Password: "12345",
}
err := validate.Struct(register)
fmt.Println(err)
}