小白教程
所有教程
关于
Search
172.69.59.43
172.69.59.43
参数设置
贡献
退出
操作
编辑
移动
保护
信息
历史
删除
查看“Golang go-playground validator 包中文教程”的源代码
本页内容
上一节:
Go_语言开发工具
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[Category:Goalng 教程|25]] 在Web开发中经常会对用户输入数据进行校验,或者在提供API给第三方使用时候需要对字段进行校验,防止脏数据和恶意请求。 Golang官方维护了 '''go-playground/validator'''<ref>https://github.com/go-playground/validator</ref> 是使用最广泛数据校验的包,自带了非常多常用的校验规则。其基于标签实现结构和单个字段的值验证。 == 特性 == * 使用验证标签或自定义验证器进行跨字段和跨结构验证。 * slice、array 和 map 层级校验支持,允许验证多维字段的任何或所有级别。 * 支持对 map key 和 value 以进行验证 * 支持处理自定义字段类型,例如 sql driver * 重命名验证标签,允许将多个验证映射到单个标签,以便更轻松地定义struct上的验证规则 * 支持提取验证数据字段的名称,例如可以指定在验证时提取 JSON 名称,并使其在生成的 FieldError 中可用 * 可设置的 i18n 错误消息。 * gin web 框架的默认验证器 == 安装 == <sample title="" desc=""> go get github.com/go-playground/validator/v10 </sample> <sample title="代码中引入包" desc=""> import "github.com/go-playground/validator/v10" </sample> == 简单的用法示例<ref>https://github.com/go-playground/validator/blob/master/_examples/simple/main.go</ref> == 可以看出我们只用在结构体的字段上加上对应的'''<nowiki>`validate:"xx"`</nowiki>'''即可添加对应验证规则。 <sample title="" desc="" hererun="s"> package main import ( "fmt" "github.com/go-playground/validator/v10" ) // User contains user information type User struct { FirstName string `validate:"required"` LastName string `validate:"required"` Age uint8 `validate:"gte=0,lte=130"` Email string `validate:"required,email"` FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla' Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage... } // Address houses a users address information type Address struct { Street string `validate:"required"` City string `validate:"required"` Planet string `validate:"required"` Phone string `validate:"required"` } // use a single instance of Validate, it caches struct info var validate *validator.Validate func main() { validate = validator.New() validateStruct() validateVariable() } func validateStruct() { address := &Address{ Street: "Eavesdown Docks", Planet: "Persphone", Phone: "none", } user := &User{ FirstName: "Badger", LastName: "Smith", Age: 135, Email: "Badger.Smith@gmail.com", FavouriteColor: "#000-", Addresses: []*Address{address}, } // returns nil or ValidationErrors ( []FieldError ) err := validate.Struct(user) if err != nil { // this check is only needed when your code could produce // an invalid value for validation such as interface with nil // value most including myself do not usually have code like this. if _, ok := err.(*validator.InvalidValidationError); ok { fmt.Println(err) return } for _, err := range err.(validator.ValidationErrors) { fmt.Println(err.Namespace()) fmt.Println(err.Field()) fmt.Println(err.StructNamespace()) fmt.Println(err.StructField()) fmt.Println(err.Tag()) fmt.Println(err.ActualTag()) fmt.Println(err.Kind()) fmt.Println(err.Type()) fmt.Println(err.Value()) fmt.Println(err.Param()) fmt.Println() } // from here you can create your own error messages in whatever language you wish return } // save user to database } func validateVariable() { myEmail := "joeybloggs.gmail.com" errs := validate.Var(myEmail, "required,email") if errs != nil { fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag return } // email ok, move on } </sample> == 验证规则 == === 字段验证规则 === <blockquote> 提示: cs为cross-struct, 跨字段验证。 eqfield=ConfirmPassword eqcsfield=InnerStructField.Field </blockquote> {| class="wikitable" |- ! 标签 ! 说明 |- | eqcsfield | 字段等于另一个字段(相对) |- | eqfield | 字段等于另一个字段 |- | fieldcontains | 字段包含 |- | fieldexcludes | 字段不包含 |- | gtcsfield | 字段大于另一个相对字段 |- | gtecsfield | 大于或等于另一个相对字段的字段 |- | gtefield | 大于或等于另一个字段的字段 |- | gtfield |字段大于其他字段 |- | ltcsfield |小于另一个相对字段 |- | ltecsfield | 小于或等于另一个相对字段 |- | ltefield | 小于或等于另一个字段 |- | ltfield | 小于另一个字段 |- | necsfield | 字段不等于另一个字段(相对) |- | nefield | 字段不等于其他字段 |} === 网络相关验证规则 === {| class="wikitable" |- ! Tag ! Description |- | cidr | Classless Inter-Domain Routing CIDR |- | cidrv4 | Classless Inter-Domain Routing CIDRv4 |- | cidrv6 | Classless Inter-Domain Routing CIDRv6 |- | datauri | Data URL |- | fqdn | Full Qualified Domain Name (FQDN) |- | hostname | Hostname RFC 952 |- | hostname_port | HostPort |- | hostname_rfc1123 | Hostname RFC 1123 |- | ip | Internet Protocol Address IP |- | ip4_addr | Internet Protocol Address IPv4 |- | ip6_addr | Internet Protocol Address IPv6 |- | ip_addr | Internet Protocol Address IP |- | ipv4 | Internet Protocol Address IPv4 |- | ipv6 | Internet Protocol Address IPv6 |- | mac | Media Access Control Address MAC |- | tcp4_addr | Transmission Control Protocol Address TCPv4 |- | tcp6_addr | Transmission Control Protocol Address TCPv6 |- | tcp_addr | Transmission Control Protocol Address TCP |- | udp4_addr | User Datagram Protocol Address UDPv4 |- | udp6_addr | User Datagram Protocol Address UDPv6 |- | udp_addr | User Datagram Protocol Address UDP |- | unix_addr | Unix domain socket end point Address |- | uri | URI String |- | url | URL String |- | url_encoded | URL Encoded |- | urn_rfc2141 | Urn RFC 2141 String |} === Strings === {| class="wikitable" |- ! 标签 ! 描述 |- | alpha | 仅字幕 |- | alphanum | 字母数字 |- | alphanumunicode | Unicode字母数字 |- | alphaunicode | Unicode字母 |- | ascii | ASCII |- | boolean | Boolean |- | contains | 包含 |- | containsany | 包含任何数据 |- | containsrune | 包含rune字符 |- | endsnotwith | 结尾不为 |- | endswith | 结尾为 |- | excludes | 排除 |- | excludesall | 全部排除 |- | excludesrune | 排除rune字符 |- | lowercase | 小写字母 |- | multibyte | 多字节字符 |- | number | 数字 |- | numeric | 数字 |- | printascii | 可打印ASCII |- | startsnotwith | 开头不是 |- | startswith | 开头为 |- | uppercase | 大写 |} === 格式 === {| class="wikitable" |- ! 标签 ! 描述 |- | base64 | Base64 String |- | base64url | Base64URL String |- | bic | Business Identifier Code (ISO 9362) |- | bcp47_language_tag | Language tag (BCP 47) |- | btc_addr | Bitcoin Address |- | btc_addr_bech32 | Bitcoin Bech32 Address (segwit) |- | credit_card | Credit Card Number |- | datetime | Datetime |- | e164 | e164 formatted phone number |- | email | E-mail String |- | eth_addr | Ethereum Address |- | hexadecimal | Hexadecimal String |- | hexcolor | Hexcolor String |- | hsl | HSL String |- | hsla | HSLA String |- | html | HTML Tags |- | html_encoded | HTML Encoded |- | isbn | International Standard Book Number |- | isbn10 | International Standard Book Number 10 |- | isbn13 | International Standard Book Number 13 |- | iso3166_1_alpha2 | Two-letter country code (ISO 3166-1 alpha-2) |- | iso3166_1_alpha3 | Three-letter country code (ISO 3166-1 alpha-3) |- | iso3166_1_alpha_numeric | Numeric country code (ISO 3166-1 numeric) |- | iso3166_2 | Country subdivision code (ISO 3166-2) |- | iso4217 | Currency code (ISO 4217) |- | json | JSON |- | jwt | JSON Web Token (JWT) |- | latitude | Latitude |- | longitude | Longitude |- | postcode_iso3166_alpha2 | Postcode |- | postcode_iso3166_alpha2_field | Postcode |- | rgb | RGB String |- | rgba | RGBA String |- | ssn | Social Security Number SSN |- | timezone | Timezone |- | uuid | Universally Unique Identifier UUID |- | uuid3 | Universally Unique Identifier UUID v3 |- | uuid3_rfc4122 | Universally Unique Identifier UUID v3 RFC4122 |- | uuid4 | Universally Unique Identifier UUID v4 |- | uuid4_rfc4122 | Universally Unique Identifier UUID v4 RFC4122 |- | uuid5 | Universally Unique Identifier UUID v5 |- | uuid5_rfc4122 | Universally Unique Identifier UUID v5 RFC4122 |- | uuid_rfc4122 | Universally Unique Identifier UUID RFC4122 |- | md4 | MD4 hash |- | md5 | MD5 hash |- | sha256 | SHA256 hash |- | sha384 | SHA384 hash |- | sha512 | SHA512 hash |- | ripemd128 | RIPEMD-128 hash |- | ripemd128 | RIPEMD-160 hash |- | tiger128 | TIGER128 hash |- | tiger160 | TIGER160 hash |- | tiger192 | TIGER192 hash |- | semver | Semantic Versioning 2.0.0 |- | ulid | Universally Unique Lexicographically Sortable Identifier ULID |} === 比较 === {| class="wikitable" |- ! 标签 ! 描述 |- | eq | 等于 |- | gt | 大于 |- | gte | 大于或等于 |- | lt | 少于 |- | lte | 小于或等于 |- | ne | 不等于 |} === 其他 === {| class="wikitable" |- ! 标签 ! 描述 |- | dir | 目录 |- | file | 文件路径 |- | isdefault | 是默认值 |- | len | 长度 |- | max | 最大值 |- | min | 最小值 |- | oneof | 其中的一个 |- | required | 要求的 |- | required_if | 如果有,则需要 |- | required_unless | required_unless |- | required_with | Required With |- | required_with_all | Required With All |- | required_without | Required Without |- | required_without_all | Required Without All |- | excluded_if | Excluded If |- | excluded_unless | Excluded Unless |- | excluded_with | Excluded With |- | excluded_with_all | Excluded With All |- | excluded_without | Excluded Without |- | excluded_without_all | Excluded Without All |- | unique | 唯一的 |} === 别名 === {| class="wikitable" |- ! 别名 ! 标签集合 |- | iscolor | hexcolor|rgb|rgba|hsl|hsla |- | country_code | iso3166_1_alpha2|iso3166_1_alpha3|iso3166_1_alpha_numeric |} == 自定义验证规则 == 对于没有定义的验证规则标签,可以自己去定义验证规则和标签名 <sample title="" desc=""> package main import ( "fmt" "github.com/go-playground/validator/v10" ) // 设置验证的tag为is-awesome type MyStruct struct { String string `validate:"is-awesome"` } // 使用单例,这样的好处是会缓存 struct 的数据。 var validate *validator.Validate func main() { validate = validator.New() // 注册验证tag validate.RegisterValidation("is-awesome", ValidateMyVal) s := MyStruct{String: "awesome"} err := validate.Struct(s) if err != nil { fmt.Printf("Err(s):\n%+v\n", err) } s.String = "not awesome" err = validate.Struct(s) if err != nil { fmt.Printf("Err(s):\n%+v\n", err) } } // ValidateMyVal 实现 validator.Func func ValidateMyVal(fl validator.FieldLevel) bool { return fl.Field().String() == "awesome" } </sample> == 国际化中文提示信息支持 == <sample title="" desc=""> package main import ( "fmt" "github.com/go-playground/locales/zh" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" zh_translations "github.com/go-playground/validator/v10/translations/zh" ) // User contains user information type User struct { FirstName string `validate:"required"` LastName string `validate:"required"` Age uint8 `validate:"gte=0,lte=130"` Email string `validate:"required,email"` FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla' Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage... } // Address houses a users address information type Address struct { Street string `validate:"required"` City string `validate:"required"` Planet string `validate:"required"` Phone string `validate:"required"` } // use a single instance , it caches struct info var ( uni *ut.UniversalTranslator validate *validator.Validate ) func main() { // NOTE: ommitting allot of error checking for brevity zh := zh.New() uni = ut.New(zh, zh) // this is usually know or extracted from http 'Accept-Language' header // also see uni.FindTranslator(...) trans, _ := uni.GetTranslator("zh") validate = validator.New() zh_translations.RegisterDefaultTranslations(validate, trans) translateAll(trans) translateIndividual(trans) translateOverride(trans) // yep you can specify your own in whatever locale you want! } func translateAll(trans ut.Translator) { type User struct { Username string `validate:"required"` Tagline string `validate:"required,lt=10"` Tagline2 string `validate:"required,gt=1"` } user := User{ Username: "Joeybloggs", Tagline: "This tagline is way too long.", Tagline2: "1", } err := validate.Struct(user) if err != nil { // translate all error at once errs := err.(validator.ValidationErrors) // returns a map with key = namespace & value = translated error // NOTICE: 2 errors are returned and you'll see something surprising // translations are i18n aware!!!! // eg. '10 characters' vs '1 character' fmt.Println(errs.Translate(trans)) } } func translateIndividual(trans ut.Translator) { type User struct { Username string `validate:"required"` } var user User err := validate.Struct(user) if err != nil { errs := err.(validator.ValidationErrors) for _, e := range errs { // can translate each error one at a time. fmt.Println(e.Translate(trans)) } } } func translateOverride(trans ut.Translator) { validate.RegisterTranslation("required", trans, func(ut ut.Translator) error { return ut.Add("required", "{0} must have a value!", true) // see universal-translator for details }, func(ut ut.Translator, fe validator.FieldError) string { t, _ := ut.T("required", fe.Field()) return t }) type User struct { Username string `validate:"required"` } var user User err := validate.Struct(user) if err != nil { errs := err.(validator.ValidationErrors) for _, e := range errs { // can translate each error one at a time. fmt.Println(e.Translate(trans)) } } } </sample> <sample title="字段校验提示会变为中文" desc="" > map[User.Tagline:Tagline长度必须小于10个字符 User.Tagline2:Tagline2长度必须大于1个字符] Username为必填字段 Username must have a value! </sample> === 支持的语言 === * ar * en * es * fa * fr * id * it * ja * nl * pt * pt_BR * ru * tr * vi * zh * zh_tw
返回至“
Golang go-playground validator 包中文教程
”。
上一节:
Go_语言开发工具