使用之前,首先要获取validator
这个库:
$ go get github.com/go-playground/validator/v10
golang http 请求参数校验工具,具备复杂参数校验规则。
标记 | 标记说明 |
, | 多操作符分割 |
| | 或操作 |
- | 跳过字段验证 |
标记 | 标记说明 | 例 |
required | 必填 | Field或Struct?validate:"required" |
omitempty | 空时忽略 | Field或Struct?validate:"omitempty" |
len | 长度 | Field?validate:"len=0" |
eq | 等于 | Field?validate:"eq=0" |
gt | 大于 | Field?validate:"gt=0" |
gte | 大于等于 | Field?validate:"gte=0" |
lt | 小于 | Field?validate:"lt=0" |
lte | 小于等于 | Field?validate:"lte=0" |
eqfield | 同一结构体字段相等 | Field?validate:"eqfield=Field2" |
nefield | 同一结构体字段不相等 | Field?validate:"nefield=Field2" |
gtfield | 大于同一结构体字段 | Field?validate:"gtfield=Field2" |
gtefield | 大于等于同一结构体字段 | Field?validate:"gtefield=Field2" |
ltfield | 小于同一结构体字段 | Field?validate:"ltfield=Field2" |
ltefield | 小于等于同一结构体字段 | Field?validate:"ltefield=Field2" |
eqcsfield | 跨不同结构体字段相等 | Struct1.Field?validate:"eqcsfield=Struct2.Field2" |
necsfield | 跨不同结构体字段不相等 | Struct1.Field?validate:"necsfield=Struct2.Field2" |
gtcsfield | 大于跨不同结构体字段 | Struct1.Field?validate:"gtcsfield=Struct2.Field2" |
gtecsfield | 大于等于跨不同结构体字段 | Struct1.Field?validate:"gtecsfield=Struct2.Field2" |
ltcsfield | 小于跨不同结构体字段 | Struct1.Field?validate:"ltcsfield=Struct2.Field2" |
ltecsfield | 小于等于跨不同结构体字段 | Struct1.Field?validate:"ltecsfield=Struct2.Field2" |
min | 最大值 | Field?validate:"min=1" |
max | 最小值 | Field?validate:"max=2" |
structonly | 仅验证结构体,不验证任何结构体字段 | Struct?validate:"structonly" |
nostructlevel | 不运行任何结构级别的验证 | Struct?validate:"nostructlevel" |
dive | 向下延伸验证,多层向下需要多个dive标记 | [][]string?validate:"gt=0,dive,len=1,dive,required" |
dive Keys & EndKeys | 与dive同时使用,用于对map对象的键的和值的验证,keys为键,endkeys为值 | map[string]string?validate:"gt=0,dive,keys,eq=1|eq=2,endkeys,required" |
required_with | 其他字段其中一个不为空且当前字段不为空 | Field?validate:"required_with=Field1 Field2" |
required_with_all | 其他所有字段不为空且当前字段不为空 | Field?validate:"required_with_all=Field1 Field2" |
required_without | 其他字段其中一个为空且当前字段不为空 | Field `validate:"required_without=Field1 Field2" |
required_without_all | 其他所有字段为空且当前字段不为空 | Field?validate:"required_without_all=Field1 Field2" |
isdefault | 是默认值 | Field?validate:"isdefault=0" |
oneof | 其中之一 | Field?validate:"oneof=5 7 9" |
containsfield | 字段包含另一个字段 | Field?validate:"containsfield=Field2" |
excludesfield | 字段不包含另一个字段 | Field?validate:"excludesfield=Field2" |
unique | 是否唯一,通常用于切片或结构体 | Field?validate:"unique" |
alphanum | 字符串值是否只包含 ASCII 字母数字字符 | Field?validate:"alphanum" |
alphaunicode | 字符串值是否只包含 unicode 字符 | Field?validate:"alphaunicode" |
alphanumunicode | 字符串值是否只包含 unicode 字母数字字符 | Field?validate:"alphanumunicode" |
numeric | 字符串值是否包含基本的数值 | Field?validate:"numeric" |
hexadecimal | 字符串值是否包含有效的十六进制 | Field?validate:"hexadecimal" |
hexcolor | 字符串值是否包含有效的十六进制颜色 | Field?validate:"hexcolor" |
lowercase | 符串值是否只包含小写字符 | Field?validate:"lowercase" |
uppercase | 符串值是否只包含大写字符 | Field?validate:"uppercase" |
| 字符串值包含一个有效的电子邮件 | Field?validate:"email" |
json | 字符串值是否为有效的 JSON | Field?validate:"json" |
file | 符串值是否包含有效的文件路径,以及该文件是否存在于计算机上 | Field?validate:"file" |
url | 符串值是否包含有效的 url | Field?validate:"url" |
uri | 符串值是否包含有效的 uri | Field?validate:"uri" |
base64 | 字符串值是否包含有效的 base64值 | Field?validate:"base64" |
contains | 字符串值包含子字符串值 | Field?validate:"contains=@" |
containsany | 字符串值包含子字符串值中的任何字符 | Field?validate:"containsany=abc" |
containsrune | 字符串值包含提供的特殊符号值 | Field?validate:"containsrune=?" |
excludes | 字符串值不包含子字符串值 | Field?validate:"excludes=@" |
excludesall | 字符串值不包含任何子字符串值 | Field?validate:"excludesall=abc" |
excludesrune | 字符串值不包含提供的特殊符号值 | Field?validate:"containsrune=?" |
startswith | 字符串以提供的字符串值开始 | Field?validate:"startswith=abc" |
endswith | 字符串以提供的字符串值结束 | Field?validate:"endswith=abc" |
ip | 字符串值是否包含有效的 IP 地址 | Field?validate:"ip" |
ipv4 | 字符串值是否包含有效的 ipv4地址 | Field?validate:"ipv4" |
datetime | 字符串值是否包含有效的 日期 | Field?validate:"datetime" |
type Test struct {
Field1 string `validate:"excludesall=|"` // 错误
Field2 string `validate:"excludesall=0x7C"` // 正确.
}
// 初始化翻译器
func validateInit() {
zh_ch := zh.New()
uni := ut.New(zh_ch) // 万能翻译器,保存所有的语言环境和翻译数据
Trans, _ = uni.GetTranslator("zh") // 翻译器
Validate = validator.New()
_ = zh_translations.RegisterDefaultTranslations(Validate, Trans)
// 添加额外翻译
_ = Validate.RegisterTranslation("required_without", Trans, func(ut ut.Translator) error {
return ut.Add("required_without", "{0} 为必填字段!", true)
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("required_without", fe.Field())
return t
})
}
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type RegisterRequest struct {
Username string `json:"username" binding:"required"`
Nickname string `json:"nickname" binding:"required"`
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required"`
Age uint8 `json:"age" binding:"gte=1,lte=120"`
}
func main() {
router := gin.Default()
router.POST("register", Register)
router.Run(":9999")
}
func Register(c *gin.Context) {
var r RegisterRequest
err := c.ShouldBindJSON(&r)
if err != nil {
fmt.Println("register failed")
c.JSON(http.StatusOK, gin.H{"msg": err.Error()})
return
}
//验证 存储操作省略.....
fmt.Println("register success")
c.JSON(http.StatusOK, "successful")
}
curl --location --request POST 'http://localhost:9999/register' \
--header 'Content-Type: application/json' \
--data-raw '{
"username": "asong",
"nickname": "golang梦工厂",
"email": "7418.com",
"password": "123",
"age": 140
}'
{
"msg": "Key: 'RegisterRequest.Email' Error:Field validation for 'Email' failed on the 'email' tag\nKey: 'RegisterRequest.Age' Error:Field validation for 'Age' failed on the 'lte' tag"
}
看这个输出结果,可以看到validator
的检验生效了,email字段不是一个合法邮箱,age字段超过了最大限制。
6.2 普通校验
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
// 实例化验证对象
var validate = validator.New()
func main() {
// 结构体验证
type Inner struct {
String string `validate:"contains=111"`
}
inner := &Inner{String: "11@"}
errs := validate.Struct(inner)
if errs != nil {
fmt.Println(errs.Error())
}
// 变量验证
m := map[string]string{"": "", "val3": "val3"}
errs = validate.Var(m, "required,dive,keys,required,endkeys,required")
if errs != nil {
fmt.Println(errs.Error())
}
}
?
?