在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
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 但是,如果需要某些自定义跨字段验证,则可以使用自定义验证来完成。 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地址(https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki)特别感谢Pieter Wuille提供的参考实现。 eth_addr //这将验证字符串值是否包含有效的以太坊地址。检查字符串的格式以确保它符合标准的以太坊地址格式完全验证被https://github.com/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: http://golang.org/src/net/mac.go?s=866:918#L29 hostname //根据RFC 952 https://tools.ietf.org/html/rfc952验证字符串值是否为有效主机名 hostname_rfc1123 or if you want to continue to use 'hostname' in your tags, create an alias //根据RFC 1123 https://tools.ietf.org/html/rfc1123验证字符串值是否为有效主机名 fqdn //这将验证字符串值是否包含有效的FQDN (完全合格的有效域名),Full Qualified Domain Name (FQDN) html //这将验证字符串值是否为HTML元素标记,包括https://developer.mozilla.org/en-US/docs/Web/HTML/Element中描述的标记。 html_encoded //这将验证字符串值是十进制或十六进制格式的正确字符引用 url_encoded //这验证了根据https://tools.ietf.org/html/rfc3986#section-2.1对字符串值进行了百分比编码(URL编码) dive例1: [][]string with validation tag "gt=0,dive,len=1,dive,required" // gt=0 被用于验证 [] // len=1 被用于验证 []string // required 被用于验证 string 例2: [][]string with validation tag "gt=0,dive,dive,required" // gt=0 被用于验证 [] // []string 将被保留验证 // required 被用于验证 string Keys & EndKeys 用法: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 within regexes.go. And the best reason, you can submit a pull request and we can keep on adding to the validation library of this package! PanicsThis 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
|
请发表评论