go结构字段验证--validator.v9
gopkg.in/go-playground/validator.v9
⾃定义验证功能
可以添加⾃定义验证功能。例:
package main
import (
"fmt"
"gopkg.in/go-playground/validator.v9"
)
type User struct {
Name string `validate:"is-zhou"`
}
func (u *User) userValidator() error { //⾃定义的验证函数,
validata := validator.New()
validata.RegisterValidation("is-zhou", ValidateMyVal) //注册验证字段和字段验证的功能
err := validata.Struct(u)
return err
}
func ValidateMyVal(f1 validator.FieldLevel) bool { //验证字段的⽅法的定义
return f1.Field().String() == "zhou"
}
func main() {
user1 := &User{
Name: "aaa",
}
err := user1.userValidator() //调⽤⾃定义验证过函数
fmt.Println(err, "err1")
user2 := &User{
Name: "zhou",
}
err = user2.userValidator()
fmt.Println(err, "err2")
}
运⾏结果
Key: 'User.Name' Error:Field validation for'Name' failed on the 'is-zhou' tag err1
<nil> err2
跨字段验证(没看懂)
跨字段验证可以通过以下标签完成:
- eqfield
- nefield
- gtfield
- gtefield
- ltfield
- ltefield
-
eqcsfield
- necsfield
- gtcsfield
- gtecsfield
- ltcsfield
- ltecsfield
但是,如果需要某些⾃定义跨字段验证,则可以使⽤⾃定义验证来完成。
为什么不只是有跨字段验证标签(即只有eqcsfield⽽不是eqfield)?
原因是效率。如果要检查同⼀结构中的字段“eqfield”,只需在同⼀结构(1级)上到该字段。但是,如果我们使⽤“eqcsfield”,它可能会降低多个级别。例:type Inner struct {
StartDate time.Time
}
type Outer struct {
InnerStructField *Inner
CreatedAt time.Time `validate:"ltecsfield=InnerStructField.StartDate"`
}
now := time.Now()
inner := &Inner{
StartDate: now,
}
outer := &Outer{
InnerStructField: inner,
CreatedAt: now,
}
errs := validate.Struct(outer)
// 注意:调⽤validate.Struct(val)时,topStruct将是传递给函数的顶级结构,
// 当调⽤validate.VarWithValue(val,field,tag)时,val将是你传递的任何东西,⽐如: struct,field ......
// 当调⽤validate.Field(field,tag)时,val将为nil
多个验证器
字段上的多个验证器将按定义的顺序处理。例:
ype Test struct {
Field `validate:"max=10,min=1"`
}
// 先验证max,然后才验证min
错误的验证不会处理,例如:
type Test struct {
Field `validate:"min=10,max=0"`
}
// this definition of min max will never succeed
使⽤验证器标签:
跨字段验证仅⽐较同⼀结构上的字段。如果需要不同结构不同字段⽐较验证,您应该实现⾃⼰的⾃定义验证器。
逗号(“,”)是验证标记的默认分隔符。如果你希望在参数中包含⼀个逗号(即excludesall =,),你将需要使⽤UTF-8⼗六进制表⽰0x2C,它在代码中被替换为逗号,因此上
⾯将变为excludesall = 0x2C。
type Test struct {
Field `validate:"excludesall=,"` // 错误⽤法,不能包含逗号
Field `validate:"excludesall=0x2C"` // 正确⽤法,使⽤UTF-8⼗六进制表⽰
}
管道(“|”)是'或'验证标签的分隔符。如果您希望在参数中包含管道,即excludesall = |你将需要使⽤UTF-8⼗六进制表⽰0x7C,它在代码中被替换为管道,所以上⾯将成为
excludesall = 0x7C
type Test struct {
Field `validate:"excludesall=|"` // BAD! Do not include a a pipe!
Field `validate:"excludesall=0x7C"` // GOOD! Use the UTF-8 hex representation.
}
Baked In Validators and Tags
以下是当前内置验证器的列表:
- //忽略字段,告诉验证跳过这个struct字段;这对于忽略嵌⼊式结构的验证尤其⽅便。(⽤法: - )
structonly //当遇到嵌套结构的字段并包含此标志时,将运⾏嵌套结构上的任何验证,但不会验证任何嵌套结构字段。如果您在程序内部知道结构有效,但需要验证它是否已分配,这⾮常有⽤。注意:结构本⾝只能使⽤“required”和“omitempty”。nostructlevel //与structonly标记相同,但不会运⾏任何结构级别验证。
omitempty //允许条件验证,例如,如果字段未设置值(由“required”验证器确定),则其他验证(如min或max)将不会运⾏,但如果设置了值,则验证将运⾏。
dive //这告诉验证者潜⼊切⽚,数组或映射,并使⽤后⾯的验证标记验证切⽚,数组或映射的该级别。还⽀持多维嵌套,您希望dive的每个级别都需要另⼀个dive标签。dive有⼀些⼦标签,'keys'和'endkeys',请参阅下⾯的keys和endkeys部分
----
required //这将验证该值不是数据类型的默认零值。数字不为0,字符串不为 " ", slices, maps, pointers, interfaces, channels and functions 不为 nil
isdefault //这验证了该值是默认值,⼏乎与所需值相反。
len=10 //对于数字,长度将确保该值等于给定的参数。对于字符串,它会检查字符串长度是否与字符数完全相同。对于切⽚,数组和map,验证元素个数。
max=10 //对于数字,max将确保该值⼩于或等于给定的参数。对于字符串,它会检查字符串长度是否最多为该字符数。对于切⽚,数组和map,验证元素个数。
min=10
eq=10 //对于字符串和数字,eq将确保该值等于给定的参数。对于切⽚,数组和map,验证元素个数。
ne=10 //和eq相反
oneof=red green (oneof=5 7 9) //对于字符串,整数和uint,oneof将确保该值是参数中的值之⼀。参数应该是由空格分隔的值列表。值可以是字符串或数字。
gt=10 //对于数字,这将确保该值⼤于给定的参数。对于字符串,它会检查字符串长度是否⼤于该字符数。对于切⽚,数组和map,它会验证元素个数。
gt //对于time.Time确保时间值⼤于time.Now.UTC()
gte=10 //⼤于等于
gte //对于time.Time确保时间值⼤于或等于time.Now.UTC()
lt=10 //⼩于
lt //对于time.Time确保时间值⼩于time.Now.UTC()
lte=10 //⼩于等于
lte //对于time.Time确保时间值⼩于等于time.Now.UTC()
----
unique //对于数组和切⽚,unique将确保没有重复项。对于map,unique将确保没有重复值。
alpha //这将验证字符串值是否仅包含ASCII字母字符
alphanum //这将验证字符串值是否仅包含ASCII字母数字字符
alphaunicode //这将验证字符串值是否仅包含unicode字符
alphanumunicode //这将验证字符串值是否仅包含unicode字母数字字符
numeric //这将验证字符串值是否包含基本数值。基本排除指数等...对于整数或浮点数,它返回true。
hexadecimal //这将验证字符串值是否包含有效的⼗六进制
hexcolor //这验证字符串值包含有效的⼗六进制颜⾊,包括#标签(#)
rgb //这将验证字符串值是否包含有效的rgb颜⾊
rgba //这将验证字符串值是否包含有效的rgba颜⾊
hsl //这将验证字符串值是否包含有效的hsl颜⾊
hsla //这将验证字符串值是否包含有效的hsla颜⾊
email //这验证字符串值包含有效的电⼦邮件这可能不符合任何rfc标准的所有可能性,但任何电⼦邮件提供商都不接受所有可能性
file //这将验证字符串值是否包含有效的⽂件路径,并且该⽂件存在于计算机上。这是使⽤os.Stat完成的,它是⼀个独⽴于平台的函数。
url //这会验证字符串值是否包含有效的url这将接受golang请求uri接受的任何url,但必须包含⼀个模式,例如http://或rtmp://
uri //这验证了字符串值包含有效的uri。这将接受uri接受的golang请求的任何uri
base64 //这将验证字符串值是否包含有效的base64值。虽然空字符串是有效的base64,但这会将空字符串报告为错误,如果您希望接受空字符串作为有效字符,则可以将此字符串与omitempty标记⼀起使⽤。
base64url //这会根据RFC4648规范验证字符串值是否包含有效的base64 URL安全值。尽管空字符串是有效的base64 URL安全值,但这会将空字符串报告为错误,如果您希望接受空字符串作为有效字符,则可以将此字符串与omitempty标记⼀起使btc_addr //这将验证字符串值是否包含有效的⽐特币地址。检查字符串的格式以确保它匹配P2PKH,P2SH三种格式之⼀并执⾏校验和验证
btc_addr_bech32 //这验证了字符串值包含bip-0173定义的有效⽐特币Bech32地址(github/bitcoin/bips/blob/diawiki)特别感谢Pieter Wuille提供的参考实现。
eth_addr //这将验证字符串值是否包含有效的以太坊地址。检查字符串的格式以确保它符合标准的以太坊地址格式完全验证被github/golang/crypto/pull/28阻⽌
contains=@ //这将验证字符串值是否包含⼦字符串值
containsany=!@#? //这将验证字符串值是否包含⼦字符串值中的任何Unicode code points。
containsrune=@ //这将验证字符串值是否包含提供的符⽂值。
excludes=@ //这验证字符串值不包含⼦字符串值。
excludesall=!@#? //这将验证字符串值在⼦字符串值中是否包含任何Unicode code points。
excludesrune=@ //这将验证字符串值是否包含提供的符⽂值。
-----
isbn //这将验证字符串值是否包含有效的isbn10或isbn13值。
isbn10 //这将验证字符串值是否包含有效的isbn10值。
isbn13 //这将验证字符串值是否包含有效的isbn13值。
uuid //这将验证字符串值是否包含有效的UUID。
uuid3 //这将验证字符串值是否包含有效的版本3 UUID。
uuid4 //这将验证字符串值是否包含有效的版本4 UUID。
uuid5 //这将验证字符串值是否包含有效的版本5 UUID。
-----
ascii //这将验证字符串值是否仅包含ASCII字符。注意:如果字符串为空,则验证为true
printascii //这将验证字符串值是否仅包含可打印的ASCII字符。注意:如果字符串为空,则验证为true。
multibyte //这将验证字符串值是否包含⼀个或多个多字节字符。注意:如果字符串为空,则验证为true
datauri //这将验证字符串值是否包含有效的DataURI。注意:这也将验证数据部分是否有效base64
latitude //这将验证字符串值是否包含有效的纬度。
longitude //这将验证字符串值是否包含有效经度。
ssn //这将验证字符串值是否包含有效的美国社会安全号码。
ip //这将验证字符串值是否包含有效的IP地址
ipv4 //这将验证字符串值是否包含有效的v4 IP地址
ipv6 //这将验证字符串值是否包含有效的v6 IP地址
cidr //这将验证字符串值是否包含有效的CIDR地址
cidrv4 //这将验证字符串值是否包含有效的v4 CIDR地址
cidrv5 //这将验证字符串值是否包含有效的v5 CIDR地址
tcp_addr //这将验证字符串值是否包含有效的可解析TCP地址
tcp4_addr //这将验证字符串值是否包含有效的可解析v4 TCP地址
tcp6_addr //这将验证字符串值是否包含有效的可解析v6 TCP地址
udp_addr //这将验证字符串值是否包含有效的可解析UDP地址
udp4_addr //这将验证字符串值是否包含有效的可解析v4 UDP地址
udp6_addr //这将验证字符串值是否包含有效的可解析v6 UDP地址
ip_addr //这将验证字符串值是否包含有效的可解析IP地址
ip4_addr //这将验证字符串值是否包含有效的可解析v4 IP地址
ip6_addr //这将验证字符串值是否包含有效的可解析v6 IP地址
unix_addr //这将验证字符串值是否包含有效的Unix地址
------
mac //这将验证字符串值是否包含有效的MAC地址
//注意:有关可接受的格式和类型,请参阅Go的ParseMAC: /src/?s=866:918#L29
hostname //根据RFC 952 /html/rfc952验证字符串值是否为有效主机名
hostname_rfc1123 or if you want to continue to use 'hostname' in your tags, create an alias //根据RFC 1123 /html/rfc1123验证字符串值是否为有效主机名
fqdn //这将验证字符串值是否包含有效的FQDN (完全合格的有效域名),Full Qualified Domain Name (FQDN)
html //这将验证字符串值是否为HTML元素标记,包括/en-US/docs/Web/HTML/Element中描述的标记。
html_encoded //这将验证字符串值是⼗进制或⼗六进制格式的正确字符引⽤
url_encoded //这验证了根据/html/rfc3986#section-2.1对字符串值进⾏了百分⽐编码(URL编码)
dive
例1:
[][]string with validation tag "gt=0,dive,len=1,dive,required"
// gt=0 被⽤于验证 []
// len=1 被⽤于验证 []string
/go字符串转数组
/ required 被⽤于验证 string
例2:
[][]string with validation tag "gt=0,dive,dive,required"
// gt=0 被⽤于验证 []
// []string 将被保留验证
// required 被⽤于验证 string
Keys & EndKeys
这些将在dive标签之后直接使⽤,并告诉验证者“keys”和“endkeys”之间的任何内容都适⽤于map的key⽽不是value;把它想象成'dive'标签,但是对于map的keys⽽不是values。还⽀持多维嵌套,您希望验证的每个级别都需要另⼀个“keys”和“endkeys”标记。这些标签仅对map有效。
⽤法:dive,keys,othertagvalidation(s),endkeys,valuevalidationtags
例1:
map[string]string with validation tag "gt=0,dive,keys,eg=1|eq=2,endkeys,required"
// gt=0 will be applied to the map itself
// eg=1|eq=2 will be applied to the map keys
// required will be applied to map values
例2:
map[[2]string]string with validation tag "gt=0,dive,keys,dive,eq=1|eq=2,endkeys,required"
// gt=0 will be applied to the map itself
// eg=1|eq=2 will be applied to each array element in the the map keys
// required will be applied to map values
Field Equals Another Field
这将在结构内或传⼊字段中针对另⼀个字段值验证字段值。
例1:
// 使⽤以下⽅法验证密码字段:
Usage: eqfield=ConfirmPassword
// 按字段验证:
validate.VarWithValue(password, confirmpassword, "eqfield")
字段等于另⼀字段(相对)
这与eqfield相同,只是它验证了相对于顶级结构提供的字段。
Usage: eqcsfield=InnerStructField.Field)
字段不等于另⼀个字段
这将在结构内或传⼊字段中针对另⼀个字段值验证字段值。
// 确认两种颜⾊不⼀样:
/
/ 对⾊域进⾏验证:
Usage: nefield=Color2
// 按字段验证:
validate.VarWithValue(color1, color2, "nefield")
字段不等于另⼀个字段(相对)
这与nefield相同,只是它验证了相对于顶级结构提供的字段。
Usage: necsfield=InnerStructField.Field
字段⼤于另⼀字段
仅对Numbers和time.Time类型有效,这将在结构内或传⼊字段中针对另⼀个字段值验证字段值。⽤法⽰例⽤于验证开始⽇期和结束⽇期:
例1:
// ⽤于验证结束字段(对⽐开始字段):
validate.Struct Usage(gtfield=Start)
例2:
// 按字段验证:
validate.VarWithValue(start, end, "gtfield")
字段⼤于另⼀个相对字段
这与gtfield相同,不同之处在于它验证了相对于顶级结构提供的字段。
Usage: gtcsfield=InnerStructField.Field
字段⼤于或等于另⼀字段
仅对Numbers和time.Time类型有效,这将在结构内或传⼊字段中针对另⼀个字段值验证字段值。⽤法⽰例⽤于验证开始⽇期和结束⽇期:
例1:
// ⽤于验证结束字段(相对开始字段):
validate.Struct Usage(gtefield=Start)
例2:
// 通过字段验证:
validate.VarWithValue(start, end, "gtefield")
字段⼤于或等于另⼀个相对字段
这与gtefield相同,只是它验证了相对于顶级结构提供的字段。
Usage: gtecsfield=InnerStructField.Field
⼩于另⼀字段
仅对Numbers和time.Time类型有效,这将在结构内或传⼊字段中针对另⼀个字段值验证字段值。⽤法⽰例⽤于验证开始⽇期和结束⽇期:
例1:
// Validation on End field using:
validate.Struct Usage(ltfield=Start)
例2:
// Validating by field:
validate.VarWithValue(start, end, "ltfield")
⼩于另⼀相对字段
这与ltfield相同,只是它验证了相对于顶级结构提供的字段。
Usage: ltcsfield=InnerStructField.Field
⼩于等于另⼀字段
仅对Numbers和time.Time类型有效,这将在结构内或传⼊字段中针对另⼀个字段值验证字段值。⽤法⽰例⽤于验证开始⽇期和结束⽇期:
例1:
// Validation on End field using:
validate.Struct Usage(ltefield=Start)
例2:
// Validating by field:
validate.VarWithValue(start, end, "ltefield")
⼩于等于另⼀相对字段
这与ltefield相同,只是它验证了相对于顶级结构提供的字段。
Usage: ltecsfield=InnerStructField.Field
======
Alias Validators and Tags(别名验证器和标签)
注意:返回error时,“FieldError”中返回的tag将是alias tag,除⾮dive tag是alias的⼀部分。dive tag之后的所有内容都不会报告为alias tag。此外,前⼀种情况中的“ActualTag”将是失败的alias中的实际tag。以下是当前内置 alias tag 的列表:
"iscolor"
alias is "hexcolor|rgb|rgba|hsl|hsla" (Usage: iscolor)
Validator notes:
regex
a regex validator won't be added because commas and = signs can be part
of a regex which conflict with the validation definitions. Although
workarounds can be made, they take away from using pure regex's.
Furthermore it's quick and dirty but the regex's become harder to
maintain and are not reusable, so it's as much a programming philosophy
as anything.
In place of this new validator functions should be created; a regex can
be used within the validator function and even be precompiled for better
efficiency
And the best reason, you can submit a pull request and we can keep on
adding to the validation library of this package!
Panics
This package panics when bad input is provided, this is by design, bad code like that should not make it to production.
type Test struct {
TestField string `validate:"nonexistantfunction=1"`
}
t := &Test{
TestField: "Test"
}
validate.Struct(t) // this will panic
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论