- Created by 郭强, last modified on Jan 16, 2024
GoFrame
框架校验组件内置了数十项常用的校验规则,校验组件是开发者最频繁使用的框架核心组件之一。
校验规则涉及到联合校验的场景时,规则中关联的参数名称会自动按照不区分大小写且忽略特殊字符的形式进行智能匹配。以下示例代码中我们均采用常用的结构体校验的方式,结构体属性中的v
标签标识validation
的缩写,用于设置该属性的校验规格。
修饰规则
修饰规则本身没有任何的校验逻辑,而是修改后续功能规则的实现逻辑。
ci
- 格式:
ci
- 说明:字段值比较在默认情况下为区分大小写严格匹配比较,通过
ci(Case Insensitive)
修饰规则,可以设置后续需要比较值的规则字段为不区分大小写。如:same
,different
,in
,not-in
等。 示例:
func Example_Rule_CaseInsensitive() { type BizReq struct { Account string `v:"required"` Password string `v:"required|ci|same:Password2"` Password2 string `v:"required"` } var ( ctx = context.Background() req = BizReq{ Account: "gf", Password: "Goframe.org", // Diff from Password2, but because of "ci", rule check passed Password2: "goframe.org", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // output: }
bail
需要特别注意:如果参数校验存在多条校验规则,并且规则中存在required*
规则和bail
修饰规则一起使用时,那么建议将required*
校验规则放置于所有规则之前,否则bail
校验规则的特性(校验失败即停止后续校验)有可能会引起后续规则的required*
规则不生效。
- 格式:
bail
- 说明:只要后续的多个校验中有一个规则校验失败则停止校验并立即返回校验结果。
- 注意:在框架的
HTTP Server
组件中,如果采用规范路由注册方式,在其自动校验特性中将会自动开启bail
修饰规则,开发者无需在Req
对象中显式设置bail
。 示例:
func Example_Rule_Bail() { type BizReq struct { Account string `v:"bail|required|length:6,16|same:QQ"` QQ string Password string `v:"required|same:Password2"` Password2 string `v:"required"` } var ( ctx = context.Background() req = BizReq{ Account: "gf", QQ: "123456", Password: "goframe.org", Password2: "goframe.org", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // output: // The Account value `gf` length must be between 6 and 16 }
foreach
- 格式:
foreach
- 说明:用于数组参数,将待检验的参数作为数组遍历,并将后一个校验规则应用于数组中的每一项。
- 版本:框架版本
>=v2.2.0
示例:
func Example_Rule_Foreach() { type BizReq struct { Value1 []int `v:"foreach|in:1,2,3"` Value2 []int `v:"foreach|in:1,2,3"` } var ( ctx = context.Background() req = BizReq{ Value1: []int{1, 2, 3}, Value2: []int{3, 4, 5}, } ) if err := g.Validator().Bail().Data(req).Run(ctx); err != nil { fmt.Println(err.String()) } // Output: // The Value2 value `4` is not in acceptable range: 1,2,3 }
功能规则
功能规则实现特定的校验逻辑,框架内置了非常丰富强大的内置校验规则。
required
- 格式:
required
- 说明:必需参数,除了支持常见的字符串,也支持
Slice/Map
类型。 示例:姓名字段
Name
为必需参数必需不能为空。func Example_Rule_Required() { type BizReq struct { ID uint `v:"required"` Name string `v:"required"` } var ( ctx = context.Background() req = BizReq{ ID: 1, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The Name field is required }
required-if
- 格式:
required-if:field,value,...
- 说明:必需参数(当任意所给定字段值与所给值相等时,即:当
field
字段的值为value
时,当前验证字段为必须参数)。多个字段以,
号分隔。 示例:当
Gender
字段为1
时WifeName
字段必须不为空, 当Gender
字段为2
时HusbandName
字段必须不为空。func Example_Rule_RequiredIf() { type BizReq struct { ID uint `v:"required" dc:"Your ID"` Name string `v:"required" dc:"Your name"` Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` WifeName string `v:"required-if:gender,1"` HusbandName string `v:"required-if:gender,2"` } var ( ctx = context.Background() req = BizReq{ ID: 1, Name: "test", Gender: 1, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The WifeName field is required }
required-unless
- 格式:
required-unless:field,value,...
- 说明:必需参数(当所给定字段值与所给值都不相等时,即:当
field
字段的值不为value
时,当前验证字段为必须参数)。多个字段以,
号分隔。 示例:当
Gender
不等于0
且Gender
不等于2
时,WifeName
必须不为空;当Id
不等于0
且Gender
不等于2
时,HusbandName
必须不为空。func Example_Rule_RequiredUnless() { type BizReq struct { ID uint `v:"required" dc:"Your ID"` Name string `v:"required" dc:"Your name"` Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` WifeName string `v:"required-unless:gender,0,gender,2"` HusbandName string `v:"required-unless:id,0,gender,2"` } var ( ctx = context.Background() req = BizReq{ ID: 1, Name: "test", Gender: 1, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The WifeName field is required; The HusbandName field is required }
required-with
- 格式:
required-with:field1,field2,...
- 说明:必需参数(当所给定任意字段值其中之一不为空时)。
示例:当
WifeName
不为空时,HusbandName
必须不为空。func Example_Rule_RequiredWith() { type BizReq struct { ID uint `v:"required" dc:"Your ID"` Name string `v:"required" dc:"Your name"` Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` WifeName string HusbandName string `v:"required-with:WifeName"` } var ( ctx = context.Background() req = BizReq{ ID: 1, Name: "test", Gender: 1, WifeName: "Ann", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The HusbandName field is required }
required-with-all
- 格式:
required-with-all:field1,field2,...
- 说明:必须参数(当所给定所有字段值全部都不为空时)。
示例:当
Id,Name,Gender,WifeName
全部不为空时,HusbandName
必须不为空。func Example_Rule_RequiredWithAll() { type BizReq struct { ID uint `v:"required" dc:"Your ID"` Name string `v:"required" dc:"Your name"` Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` WifeName string HusbandName string `v:"required-with-all:Id,Name,Gender,WifeName"` } var ( ctx = context.Background() req = BizReq{ ID: 1, Name: "test", Gender: 1, WifeName: "Ann", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The HusbandName field is required }
required-without
- 格式:
required-without:field1,field2,...
- 说明:必需参数(当所给定任意字段值其中之一为空时)。
示例:当
Id
或WifeName
为空时,HusbandName
必须不为空。func Example_Rule_RequiredWithout() { type BizReq struct { ID uint `v:"required" dc:"Your ID"` Name string `v:"required" dc:"Your name"` Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` WifeName string HusbandName string `v:"required-without:Id,WifeName"` } var ( ctx = context.Background() req = BizReq{ ID: 1, Name: "test", Gender: 1, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The HusbandName field is required }
required-without-all
- 格式:
required-without-all:field1,field2,...
- 说明:必须参数(当所给定所有字段值全部都为空时)。
示例:当
Id
和WifeName
都为空时,HusbandName
必须不为空。func Example_Rule_RequiredWithoutAll() { type BizReq struct { ID uint `v:"required" dc:"Your ID"` Name string `v:"required" dc:"Your name"` Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` WifeName string HusbandName string `v:"required-without-all:Id,WifeName"` } var ( ctx = context.Background() req = BizReq{ Name: "test", Gender: 1, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The HusbandName field is required }
date
- 格式:
date
- 说明:参数为常用日期类型,日期之间支持的连接符号
-
或/
或.
,也支持不带连接符号的8
位长度日期,格式如:2006-01-02
,2006/01/02
,2006.01.02
,20060102
示例:
func Example_Rule_Date() { type BizReq struct { Date1 string `v:"date"` Date2 string `v:"date"` Date3 string `v:"date"` Date4 string `v:"date"` Date5 string `v:"date"` } var ( ctx = context.Background() req = BizReq{ Date1: "2021-10-31", Date2: "2021.10.31", Date3: "2021-Oct-31", Date4: "2021 Octa 31", Date5: "2021/Oct/31", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Date3 value `2021-Oct-31` is not a valid date // The Date4 value `2021 Octa 31` is not a valid date // The Date5 value `2021/Oct/31` is not a valid date }
datetime
- 格式:
datetime
- 说明:参数为常用日期时间类型,其中日期之间支持的连接符号只支持
-
,格式如:2006-01-02 12:00:00
示例:
func Example_Rule_Datetime() { type BizReq struct { Date1 string `v:"datetime"` Date2 string `v:"datetime"` Date3 string `v:"datetime"` Date4 string `v:"datetime"` } var ( ctx = context.Background() req = BizReq{ Date1: "2021-11-01 23:00:00", Date2: "2021-11-01 23:00", // error Date3: "2021/11/01 23:00:00", // error Date4: "2021/Dec/01 23:00:00", // error } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Date2 value `2021-11-01 23:00` is not a valid datetime // The Date3 value `2021/11/01 23:00:00` is not a valid datetime // The Date4 value `2021/Dec/01 23:00:00` is not a valid datetime }
date-format
- 格式:
date-format:format
- 说明:判断日期是否为指定的日期/时间格式,
format
参数格式为gtime
日期格式(可以包含日期及时间),格式说明参考章节:gtime模块 示例:
date-format:Y-m-d H:i:s
func Example_Rule_DateFormat() { type BizReq struct { Date1 string `v:"date-format:Y-m-d"` Date2 string `v:"date-format:Y-m-d"` Date3 string `v:"date-format:Y-m-d H:i:s"` Date4 string `v:"date-format:Y-m-d H:i:s"` } var ( ctx = context.Background() req = BizReq{ Date1: "2021-11-01", Date2: "2021-11-01 23:00", // error Date3: "2021-11-01 23:00:00", Date4: "2021-11-01 23:00", // error } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Date2 value `2021-11-01 23:00` does not match the format: Y-m-d // The Date4 value `2021-11-01 23:00` does not match the format: Y-m-d H:i:s }
before
- 格式:
before:field
说明:判断给定的日期/时间是否在指定字段的日期/时间之前。
- 版本:框架版本
>=v2.2.0
func Example_Rule_Before() { type BizReq struct { Time1 string `v:"before:Time3"` Time2 string `v:"before:Time3"` Time3 string } var ( ctx = context.Background() req = BizReq{ Time1: "2022-09-02", Time2: "2022-09-03", Time3: "2022-09-03", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err.String()) } // Output: // The Time2 value `2022-09-03` must be before field Time3 value `2022-09-03` }
before-equal
- 格式:
before-equal:field
说明:判断给定的日期/时间是否在指定字段的日期/时间之前,或者与指定字段的日期/时间相等。
版本:框架版本
>=v2.2.0
func Example_Rule_BeforeEqual() { type BizReq struct { Time1 string `v:"before-equal:Time3"` Time2 string `v:"before-equal:Time3"` Time3 string } var ( ctx = context.Background() req = BizReq{ Time1: "2022-09-02", Time2: "2022-09-01", Time3: "2022-09-01", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Time1 value `2022-09-02` must be before or equal to field Time3 }
after
- 格式:
after:field
说明:判断给定的日期/时间是否在指定字段的日期/时间之后。
- 版本:框架版本
>=v2.2.0
func Example_Rule_After() { type BizReq struct { Time1 string Time2 string `v:"after:Time1"` Time3 string `v:"after:Time1"` } var ( ctx = context.Background() req = BizReq{ Time1: "2022-09-01", Time2: "2022-09-01", Time3: "2022-09-02", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err.String()) } // Output: // The Time2 value `2022-09-01` must be after field Time1 value `2022-09-01` }
after-equal
- 格式:
after-equal:field
说明:判断给定的日期/时间是否在指定字段的日期/时间之后,或者与指定字段的日期/时间相等。
版本:框架版本
>=v2.2.0
func Example_Rule_AfterEqual() { type BizReq struct { Time1 string Time2 string `v:"after-equal:Time1"` Time3 string `v:"after-equal:Time1"` } var ( ctx = context.Background() req = BizReq{ Time1: "2022-09-02", Time2: "2022-09-01", Time3: "2022-09-02", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Time2 value `2022-09-01` must be after or equal to field Time1 value `2022-09-02` }
array
- 格式:
array
说明:判断给定的参数是否数组格式。如果给定的参数为
JSON
数组字符串,也将检验通过。- 版本:框架版本
>=v2.2.0
func Example_Rule_Array() { type BizReq struct { Value1 string `v:"array"` Value2 string `v:"array"` Value3 string `v:"array"` Value4 []string `v:"array"` } var ( ctx = context.Background() req = BizReq{ Value1: "1,2,3", Value2: "[]", Value3: "[1,2,3]", Value4: []string{}, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Value1 value `1,2,3` is not of valid array type }
enums
- 格式:
enums
说明:校验提交的参数是否在字段类型的枚举值中。该规则需要结合
gf gen enums
命令一起使用,详情请参考:枚举维护-gen enumsfunc ExampleRule_Enums() { type Status string const ( StatusRunning Status = "Running" StatusOffline Status = "Offline" ) type BizReq struct { Id int `v:"required"` Name string `v:"required"` Status Status `v:"enums"` } var ( ctx = context.Background() req = BizReq{ Id: 1, Name: "john", Status: Status("Pending"), } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // May Output: // The Status value `Pending` should be in enums of: ["Running","Offline"] }
email
- 格式:
email
说明:
EMAIL
邮箱地址格式。func Example_Rule_Email() { type BizReq struct { MailAddr1 string `v:"email"` MailAddr2 string `v:"email"` MailAddr3 string `v:"email"` MailAddr4 string `v:"email"` } var ( ctx = context.Background() req = BizReq{ MailAddr1: "gf@goframe.org", MailAddr2: "gf@goframe", // error MailAddr3: "gf@goframe.org.cn", MailAddr4: "gf#goframe.org", // error } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The MailAddr2 value `gf@goframe` is not a valid email address // The MailAddr4 value `gf#goframe.org` is not a valid email address }
phone
- 格式:
phone
说明:大中国区手机号格式。
func Example_Rule_Phone() { type BizReq struct { PhoneNumber1 string `v:"phone"` PhoneNumber2 string `v:"phone"` PhoneNumber3 string `v:"phone"` PhoneNumber4 string `v:"phone"` } var ( ctx = context.Background() req = BizReq{ PhoneNumber1: "13578912345", PhoneNumber2: "11578912345", // error 11x not exist PhoneNumber3: "17178912345", // error 171 not exit PhoneNumber4: "1357891234", // error len must be 11 } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The PhoneNumber2 value `11578912345` is not a valid phone number // The PhoneNumber3 value `17178912345` is not a valid phone number // The PhoneNumber4 value `1357891234` is not a valid phone number }
phone-loose
- 格式:
phone
说明:宽松的手机号验证,只要满足
13、14、15、16、17、18、19
开头的11位数字都可以通过验证。可用于非严格的业务场景。func Example_Rule_PhoneLoose() { type BizReq struct { PhoneNumber1 string `v:"phone-loose"` PhoneNumber2 string `v:"phone-loose"` PhoneNumber3 string `v:"phone-loose"` PhoneNumber4 string `v:"phone-loose"` } var ( ctx = context.Background() req = BizReq{ PhoneNumber1: "13578912345", PhoneNumber2: "11578912345", // error 11x not exist PhoneNumber3: "17178912345", PhoneNumber4: "1357891234", // error len must be 11 } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The PhoneNumber2 value `11578912345` is invalid // The PhoneNumber4 value `1357891234` is invalid }
telephone
- 格式:
telephone
说明:大中国区座机电话号码,”XXXX-XXXXXXX”、”XXXX-XXXXXXXX”、”XXX-XXXXXXX”、”XXX-XXXXXXXX”、”XXXXXXX”、”XXXXXXXX”。
func Example_Rule_Telephone() { type BizReq struct { Telephone1 string `v:"telephone"` Telephone2 string `v:"telephone"` Telephone3 string `v:"telephone"` Telephone4 string `v:"telephone"` } var ( ctx = context.Background() req = BizReq{ Telephone1: "010-77542145", Telephone2: "0571-77542145", Telephone3: "20-77542145", // error Telephone4: "775421451", // error len must be 7 or 8 } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Telephone3 value `20-77542145` is not a valid telephone number // The Telephone4 value `775421451` is not a valid telephone number }
passport
- 格式:
passport
说明:通用帐号规则(字母开头,只能包含字母、数字和下划线,长度在6~18之间)。
func Example_Rule_Passport() { type BizReq struct { Passport1 string `v:"passport"` Passport2 string `v:"passport"` Passport3 string `v:"passport"` Passport4 string `v:"passport"` } var ( ctx = context.Background() req = BizReq{ Passport1: "goframe", Passport2: "1356666", // error starting with letter Passport3: "goframe#", // error containing only numbers or underscores Passport4: "gf", // error length between 6 and 18 } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Passport2 value `1356666` is not a valid passport format // The Passport3 value `goframe#` is not a valid passport format // The Passport4 value `gf` is not a valid passport format }
password
- 格式:
password
说明:通用密码规则(任意可见字符,长度在6~18之间)。
func Example_Rule_Password() { type BizReq struct { Password1 string `v:"password"` Password2 string `v:"password"` } var ( ctx = context.Background() req = BizReq{ Password1: "goframe", Password2: "gofra", // error length between 6 and 18 } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The Password2 value `gofra` is not a valid password format }
password2
- 格式:
password2
说明:中等强度密码(在通用密码规则的基础上,要求密码必须包含大小写字母和数字)。
func Example_Rule_Password2() { type BizReq struct { Password1 string `v:"password2"` Password2 string `v:"password2"` Password3 string `v:"password2"` Password4 string `v:"password2"` } var ( ctx = context.Background() req = BizReq{ Password1: "Goframe123", Password2: "gofra", // error length between 6 and 18 Password3: "Goframe", // error must contain lower and upper letters and numbers. Password4: "goframe123", // error must contain lower and upper letters and numbers. } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Password2 value `gofra` is not a valid password format // The Password3 value `Goframe` is not a valid password format // The Password4 value `goframe123` is not a valid password format }
password3
- 格式:
password3
说明:强等强度密码(在通用密码规则的基础上,必须包含大小写字母、数字和特殊字符)。
func Example_Rule_Password3() { type BizReq struct { Password1 string `v:"password3"` Password2 string `v:"password3"` Password3 string `v:"password3"` } var ( ctx = context.Background() req = BizReq{ Password1: "Goframe123#", Password2: "gofra", // error length between 6 and 18 Password3: "Goframe123", // error must contain lower and upper letters, numbers and special chars. } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Password2 value `gofra` is not a valid password format // The Password3 value `Goframe123` is not a valid password format }
postcode
- 格式:
postcode
说明:大中国区邮政编码规则。
func Example_Rule_Postcode() { type BizReq struct { Postcode1 string `v:"postcode"` Postcode2 string `v:"postcode"` Postcode3 string `v:"postcode"` } var ( ctx = context.Background() req = BizReq{ Postcode1: "100000", Postcode2: "10000", // error length must be 6 Postcode3: "1000000", // error length must be 6 } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Postcode2 value `10000` is not a valid postcode format // The Postcode3 value `1000000` is not a valid postcode format }
resident-id
- 格式: resident-id
说明:公民身份证号码。
func Example_Rule_ResidentId() { type BizReq struct { ResidentID1 string `v:"resident-id"` } var ( ctx = context.Background() req = BizReq{ ResidentID1: "320107199506285482", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The ResidentID1 value `320107199506285482` is not a valid resident id number }
bank-card
- 格式: bank-card
说明:大中国区银行卡号校验。
func Example_Rule_BankCard() { type BizReq struct { BankCard1 string `v:"bank-card"` } var ( ctx = context.Background() req = BizReq{ BankCard1: "6225760079930218", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The BankCard1 value `6225760079930218` is not a valid bank card number }
qq
- 格式:
qq
说明:腾讯QQ号码规则。
func Example_Rule_QQ() { type BizReq struct { QQ1 string `v:"qq"` QQ2 string `v:"qq"` QQ3 string `v:"qq"` } var ( ctx = context.Background() req = BizReq{ QQ1: "389961817", QQ2: "9999", // error >= 10000 QQ3: "514258412a", // error all number } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The QQ2 value `9999` is not a valid QQ number // The QQ3 value `514258412a` is not a valid QQ number }
ip
- 格式:
ip
说明:
IPv4/IPv6
地址。func Example_Rule_IP() { type BizReq struct { IP1 string `v:"ip"` IP2 string `v:"ip"` IP3 string `v:"ip"` IP4 string `v:"ip"` } var ( ctx = context.Background() req = BizReq{ IP1: "127.0.0.1", IP2: "fe80::812b:1158:1f43:f0d1", IP3: "520.255.255.255", // error >= 10000 IP4: "ze80::812b:1158:1f43:f0d1", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The IP3 value `520.255.255.255` is not a valid IP address // The IP4 value `ze80::812b:1158:1f43:f0d1` is not a valid IP address }
ipv4
- 格式:
ipv4
说明:
IPv4
地址。func Example_Rule_IPV4() { type BizReq struct { IP1 string `v:"ipv4"` IP2 string `v:"ipv4"` } var ( ctx = context.Background() req = BizReq{ IP1: "127.0.0.1", IP2: "520.255.255.255", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The IP2 value `520.255.255.255` is not a valid IPv4 address }
ipv6
- 格式:
ipv6
说明:
IPv6
地址。func Example_Rule_IPV6() { type BizReq struct { IP1 string `v:"ipv6"` IP2 string `v:"ipv6"` } var ( ctx = context.Background() req = BizReq{ IP1: "fe80::812b:1158:1f43:f0d1", IP2: "ze80::812b:1158:1f43:f0d1", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The IP2 value `ze80::812b:1158:1f43:f0d1` is not a valid IPv6 address }
mac
- 格式:
mac
说明:
MAC
地址。func Example_Rule_Mac() { type BizReq struct { Mac1 string `v:"mac"` Mac2 string `v:"mac"` } var ( ctx = context.Background() req = BizReq{ Mac1: "4C-CC-6A-D6-B1-1A", Mac2: "Z0-CC-6A-D6-B1-1A", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The Mac2 value `Z0-CC-6A-D6-B1-1A` is not a valid MAC address }
url
- 格式:
url
- 说明:URL
示例:支持以
http,https,ftp,file
开头的地址。func Example_Rule_Url() { type BizReq struct { URL1 string `v:"url"` URL2 string `v:"url"` URL3 string `v:"url"` } var ( ctx = context.Background() req = BizReq{ URL1: "http://goframe.org", URL2: "ftp://goframe.org", URL3: "ws://goframe.org", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The URL3 value `ws://goframe.org` is not a valid URL address }
domain
- 格式:
domain
- 说明:域名
示例:域名规则。
xxx.yyy
(首位必须为字母)。func Example_Rule_Domain() { type BizReq struct { Domain1 string `v:"domain"` Domain2 string `v:"domain"` Domain3 string `v:"domain"` Domain4 string `v:"domain"` } var ( ctx = context.Background() req = BizReq{ Domain1: "goframe.org", Domain2: "a.b", Domain3: "goframe#org", Domain4: "1a.2b", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Domain3 value `goframe#org` is not a valid domain format // The Domain4 value `1a.2b` is not a valid domain format }
size
- 格式:
size:size
说明:参数长度为
size
(长度参数为整形),注意底层使用Unicode
计算长度,因此中文一个汉字占1
个长度单位。func Example_Rule_Size() { type BizReq struct { Size1 string `v:"size:10"` Size2 string `v:"size:5"` } var ( ctx = context.Background() req = BizReq{ Size1: "goframe欢迎你", Size2: "goframe", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The Size2 value `goframe` length must be 5 }
length
- 格式:
length:min,max
说明:参数长度为
min
到max
(长度参数为整形),注意底层使用Unicode
计算长度,因此中文一个汉字占1
个长度单位。func Example_Rule_Length() { type BizReq struct { Length1 string `v:"length:5,10"` Length2 string `v:"length:10,15"` } var ( ctx = context.Background() req = BizReq{ Length1: "goframe欢迎你", Length2: "goframe", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The Length2 value `goframe` length must be between 10 and 15 }
min-length
- 格式:
min-length:min
说明:参数长度最小为
min
(长度参数为整形),注意底层使用Unicode
计算长度,因此中文一个汉字占1
个长度单位。func Example_Rule_MinLength() { type BizReq struct { MinLength1 string `v:"min-length:10"` MinLength2 string `v:"min-length:8"` } var ( ctx = context.Background() req = BizReq{ MinLength1: "goframe欢迎你", MinLength2: "goframe", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The MinLength2 value `goframe` length must be equal or greater than 8 }
max-length
- 格式:
max-length:max
说明:参数长度最大为
max
(长度参数为整形),注意底层使用Unicode
计算长度,因此中文一个汉字占1
个长度单位。func Example_Rule_MaxLength() { type BizReq struct { MaxLength1 string `v:"max-length:10"` MaxLength2 string `v:"max-length:5"` } var ( ctx = context.Background() req = BizReq{ MaxLength1: "goframe欢迎你", MaxLength2: "goframe", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The MaxLength2 value `goframe` length must be equal or lesser than 5 }
between
- 格式:
between:min,max
说明:参数大小为
min
到max
(支持整形和浮点类型参数)。func Example_Rule_Between() { type BizReq struct { Age1 int `v:"between:1,100"` Age2 int `v:"between:1,100"` Score1 float32 `v:"between:0,10"` Score2 float32 `v:"between:0,10"` } var ( ctx = context.Background() req = BizReq{ Age1: 50, Age2: 101, Score1: 9.8, Score2: -0.5, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Age2 value `101` must be between 1 and 100 // The Score2 value `-0.5` must be between 0 and 10 }
min
- 格式:
min:min
说明:参数大小最小为
min
(支持整形和浮点类型参数)。func Example_Rule_Min() { type BizReq struct { Age1 int `v:"min:100"` Age2 int `v:"min:100"` Score1 float32 `v:"min:10"` Score2 float32 `v:"min:10"` } var ( ctx = context.Background() req = BizReq{ Age1: 50, Age2: 101, Score1: 9.8, Score2: 10.1, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Age1 value `50` must be equal or greater than 100 // The Score1 value `9.8` must be equal or greater than 10 }
max
- 格式:
max:max
说明:参数大小最大为
max
(支持整形和浮点类型参数)。func Example_Rule_Max() { type BizReq struct { Age1 int `v:"max:100"` Age2 int `v:"max:100"` Score1 float32 `v:"max:10"` Score2 float32 `v:"max:10"` } var ( ctx = context.Background() req = BizReq{ Age1: 99, Age2: 101, Score1: 9.9, Score2: 10.1, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Age2 value `101` must be equal or lesser than 100 // The Score2 value `10.1` must be equal or lesser than 10 }
json
- 格式:
json
说明:判断数据格式为
JSON
。func Example_Rule_Json() { type BizReq struct { JSON1 string `v:"json"` JSON2 string `v:"json"` } var ( ctx = context.Background() req = BizReq{ JSON1: "{\"name\":\"goframe\",\"author\":\"郭强\"}", JSON2: "{\"name\":\"goframe\",\"author\":\"郭强\",\"test\"}", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The JSON2 value `{"name":"goframe","author":"郭强","test"}` is not a valid JSON string }
integer
- 格式:
integer
说明:整数(正整数或者负整数)。
func Example_Rule_Integer() { type BizReq struct { Integer string `v:"integer"` Float string `v:"integer"` Str string `v:"integer"` } var ( ctx = context.Background() req = BizReq{ Integer: "100", Float: "10.0", Str: "goframe", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Float value `10.0` is not an integer // The Str value `goframe` is not an integer }
float
- 格式:
float
说明:浮点数。
func Example_Rule_Float() { type BizReq struct { Integer string `v:"float"` Float string `v:"float"` Str string `v:"float"` } var ( ctx = context.Background() req = BizReq{ Integer: "100", Float: "10.0", Str: "goframe", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(err) } // Output: // The Str value `goframe` is invalid }
boolean
- 格式:
boolean
说明:布尔值(
1
,true
,on
,yes
为true
|0
,false
,off
,no
,""
为false
)。func Example_Rule_Boolean() { type BizReq struct { Boolean bool `v:"boolean"` Integer int `v:"boolean"` Float float32 `v:"boolean"` Str1 string `v:"boolean"` Str2 string `v:"boolean"` Str3 string `v:"boolean"` } var ( ctx = context.Background() req = BizReq{ Boolean: true, Integer: 1, Float: 10.0, Str1: "on", Str2: "", Str3: "goframe", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Float value `10` field must be true or false // The Str3 value `goframe` field must be true or false }
same
- 格式:
same:field
- 说明:参数值必需与
field
字段参数的值相同。 示例:在用户注册时,提交密码
Password
和确认密码Password2
必须相等(服务端校验)。func Example_Rule_Same() { type BizReq struct { Name string `v:"required"` Password string `v:"required|same:Password2"` Password2 string `v:"required"` } var ( ctx = context.Background() req = BizReq{ Name: "gf", Password: "goframe.org", Password2: "goframe.net", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The Password value `goframe.org` must be the same as field Password2 }
different
- 格式:
different:field
- 说明:参数值不能与
field
字段参数的值相同。 示例:备用邮箱
OtherMailAddr
和邮箱地址MailAddr
必须不相同。func Example_Rule_Different() { type BizReq struct { Name string `v:"required"` MailAddr string `v:"required"` ConfirmMailAddr string `v:"required|different:MailAddr"` } var ( ctx = context.Background() req = BizReq{ Name: "gf", MailAddr: "gf@goframe.org", ConfirmMailAddr: "gf@goframe.org", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The ConfirmMailAddr value `gf@goframe.org` must be different from field MailAddr }
eq
- 格式:
eq:field
说明:参数值必需与
field
字段参数的值相同。same
规则的别名,功能同same
规则。- 版本:框架版本
>=v2.2.0
func Example_Rule_EQ() { type BizReq struct { Name string `v:"required"` Password string `v:"required|eq:Password2"` Password2 string `v:"required"` } var ( ctx = context.Background() req = BizReq{ Name: "gf", Password: "goframe.org", Password2: "goframe.net", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The Password value `goframe.org` must be equal to field Password2 value `goframe.net` }
not-eq
- 格式:
not-eq:field
说明:参数值必需与
field
字段参数的值不相同。different
规则的别名,功能同different
规则。- 版本:框架版本
>=v2.2.0
func Example_Rule_NotEQ() { type BizReq struct { Name string `v:"required"` MailAddr string `v:"required"` OtherMailAddr string `v:"required|not-eq:MailAddr"` } var ( ctx = context.Background() req = BizReq{ Name: "gf", MailAddr: "gf@goframe.org", OtherMailAddr: "gf@goframe.org", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The OtherMailAddr value `gf@goframe.org` must not be equal to field MailAddr value `gf@goframe.org` }
gt
- 格式:
gt:field
说明:参数值必需大于给定字段对应的值。
- 版本:框架版本
>=v2.2.0
func Example_Rule_GT() { type BizReq struct { Value1 int Value2 int `v:"gt:Value1"` Value3 int `v:"gt:Value1"` } var ( ctx = context.Background() req = BizReq{ Value1: 1, Value2: 1, Value3: 2, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err.String()) } // Output: // The Value2 value `1` must be greater than field Value1 value `1` }
gte
- 格式:
gte:field
说明:参数值必需大于或等于给定字段对应的值。
- 版本:框架版本
>=v2.2.0
func Example_Rule_GTE() { type BizReq struct { Value1 int Value2 int `v:"gte:Value1"` Value3 int `v:"gte:Value1"` } var ( ctx = context.Background() req = BizReq{ Value1: 2, Value2: 1, Value3: 2, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err.String()) } // Output: // The Value2 value `1` must be greater than or equal to field Value1 value `2` }
lt
- 格式:
lt:field
说明:参数值必需小于给定字段对应的值。
- 版本:框架版本
>=v2.2.0
func Example_Rule_LT() { type BizReq struct { Value1 int Value2 int `v:"lt:Value1"` Value3 int `v:"lt:Value1"` } var ( ctx = context.Background() req = BizReq{ Value1: 2, Value2: 1, Value3: 2, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err.String()) } // Output: // The Value3 value `2` must be lesser than field Value1 value `2` }
lte
- 格式:
lte:field
说明:参数值必需小于或等于给定字段对应的值。
- 版本:框架版本
>=v2.2.0
func Example_Rule_LTE() { type BizReq struct { Value1 int Value2 int `v:"lte:Value1"` Value3 int `v:"lte:Value1"` } var ( ctx = context.Background() req = BizReq{ Value1: 1, Value2: 1, Value3: 2, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err.String()) } // Output: // The Value3 value `2` must be lesser than or equal to field Value1 value `1` }
in
- 格式:
in:value1,value2,...
- 说明:参数值应该在
value1,value2,...
中(字符串匹配)。 示例:性别字段
Gender
的值必须在0/1/2
中。func Example_Rule_In() { type BizReq struct { ID uint `v:"required" dc:"Your Id"` Name string `v:"required" dc:"Your name"` Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` } var ( ctx = context.Background() req = BizReq{ ID: 1, Name: "test", Gender: 3, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The Gender value `3` is not in acceptable range: 0,1,2 }
not-in
- 格式:
not-in:value1,value2,...
- 说明:参数值不应该在
value1,value2,...
中(字符串匹配)。 示例:无效索引
InvalidIndex
的值必须不在-1/0/1
中。func Example_Rule_NotIn() { type BizReq struct { ID uint `v:"required" dc:"Your Id"` Name string `v:"required" dc:"Your name"` InvalidIndex uint `v:"not-in:-1,0,1"` } var ( ctx = context.Background() req = BizReq{ ID: 1, Name: "test", InvalidIndex: 1, } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Println(err) } // Output: // The InvalidIndex value `1` must not be in range: -1,0,1 }
regex
- 格式:
regex:pattern
说明:参数值应当满足正则匹配规则
pattern
func Example_Rule_Regex() { type BizReq struct { Regex1 string `v:"regex:[1-9][0-9]{4,14}"` Regex2 string `v:"regex:[1-9][0-9]{4,14}"` Regex3 string `v:"regex:[1-9][0-9]{4,14}"` } var ( ctx = context.Background() req = BizReq{ Regex1: "1234", Regex2: "01234", Regex3: "10000", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Regex1 value `1234` must be in regex of: [1-9][0-9]{4,14} // The Regex2 value `01234` must be in regex of: [1-9][0-9]{4,14} }
not-regex
- 格式:
not-regex:pattern
说明:参数值不应当满足正则匹配规则
pattern
。- 版本:框架版本
>=v2.2.0
func Example_Rule_NotRegex() { type BizReq struct { Regex1 string `v:"regex:\\d{4}"` Regex2 string `v:"not-regex:\\d{4}"` } var ( ctx = context.Background() req = BizReq{ Regex1: "1234", Regex2: "1234", } ) if err := g.Validator().Data(req).Run(ctx); err != nil { fmt.Print(gstr.Join(err.Strings(), "\n")) } // Output: // The Regex2 value `1234` should not be in regex of: \d{4} }
- No labels
35 Comments
郭强
刘洋
你可以使用
min
规则,不一定要使用required
规则。如果是结构体属性的校验,请参考 数据校验-Struct校验 章节。linhaijian
required
规则可以用min
来代替,那required-if
怎么办呢?郭强
目前可以使用指针属性替代,后续会改进一下请求参数的校验处理。
xx
required-without
和required-without-all
根本用不了,也没例子,测试过了吗?xx
Nickname
的required-with
也不行。郭强
这个是因为
*gtime.Time
类型在required-with
规则下会失效,你试试最新的master
分支。贾君宇
能否加一个终止校验的标志,像laravel一样,出现err就停止下一个检测
郭强
你可以提个
issue
记录下。ezreal_rao
可以校验是否为数组吗?就像`laravel`中的`array`校验
郭强
目前内置规则不支持,你可以考虑自定义校验规则,甚至可以覆盖已有的内置规则,详情请参考章节:数据校验-自定义规则
jason
可以加个 exists 和 unique 验证规则吗
海亮
详细说说场景,带上举例。可以自定义规则的数据校验-自定义规则
jason
检查此字段值在数据表里是否存在或唯一性,支持自定义字段、表名、数据库名称。定义后就不用每个场景都需要手动写一遍 sql 查询并且手动校验,业务中会经常用到
郭强
你这种业务强相关的,自定义规则实现吧:数据校验-自定义规则 一次注册四处使用。也欢迎贡献通用性的规则。
ljs
正则匹配怎么满足带“|”的表达式
海亮
zippy_ppo
能否考虑增加主动获取全部检测结果的情况,特别是后台的开发中,不需要前端后端都写一套验证规则。
yidashi
email不生效啊
lowe
required-if 多字段是与关系,还是或关系
看源码是或关系,只要满足一个字段的条件就为必填
a632079
您好,我想问一下 required-if 等条件语句,允许直接使用 enum 创建的 Alias 吗?比如说我定义了个 Enum 1,2,3;我希望校验的时候只允许 2,3 时需要此字段,能否直接使用 Enum 创建的 Alias,比如 EnumB, EnumC。
overbeck.jack
enums
和email
规则无法使用 郭强 请问正确的示例是怎么样的?可以给出吗??使用规范化路由时,规则
enums
报错请求结构体如下
overbeck.jack
有很多规则似乎都是不可用的,这些是有测试过的吗????
郭强 目前我测试一下就已经挺多用不了
enums
email
url
domain
陈鹏
或者条件怎么些,一个字段内phone或者
email
接收是一个字段,但是两个条件任意一个符合就行,只看到有并且,没看到或关系呢,只能自己实现吗zhc
type HelloReq struct {
g.Meta `path:"/hello" tags:"Hello" method:"post" summary:"You first hello api"`
TestA string ` json:"ta" v:"required" `
}
//直接发送下面的内容会提示错误参数
{
"ta":"111"
}
{
"code": 51,
"message": "The TestA field is required",
"data": null
}
如果这样发送就没问题
{
"testa":"111"
}
或者去掉v:"required"这个 然后发送"ta"也可以
感觉josn标签和v:"required"有点冲突
huruhi
规范路由的 Req 使用
并不是顺序验证,请问下如何指定顺序
砰砰声
这个校验规则,看得亲切,要是可以设置应用场景的话,那就更好了
anuo
校验规则都还有一堆bug,你还想添加场景,bug更多
ae86
哪些bug?提issue,让俺去贡献一波
Before80
关于
domain
这个校验规则,您写到:“示例:域名规则。xxx.yyy
(首位必须为字母)。“,其中“首位必须为字母”,应该是有点问题,现在有些域名是以数字开头的,例如:99designs.com,123example.com 等等。周润发
wln32
你说的是那个规则不能正确校验,array规则适用于字符串类型应该
hotter23
请教一下
请求 curl http://127.0.0.1:8000/get-user-info
2024-06-03 15:37:36.150 {608cfa0c6f6ed517fba64662b17bd51e} 200 "POST http 127.0.0.1:8000 /get-user-info HTTP/1.1" 365.975, 127.0.0.1, "", "PostmanRuntime/7.37.3", 51, "Validation Failed", ""
Stack:
The UserId field is required
这样会直接退出堆栈,如何解决?
hotter23
我自己解决了,需要在 中间件中对错误/成功 做统一处理,就可以 正常返回http 请求了
叮当猫
中文文档看得比英文还累,博主不喜欢使用标点符号,也不喜欢用定语,经常遇到一句话都长到难以理解。
比如下面这2句话:
“规则中关联的参数名称会自动按照不区分大小写且忽略特殊字符的形式进行智能匹配。”
”字段值比较在默认情况下为区分大小写严格匹配比较。“
regsey
如何校验[]string的长度呢,max、max-length貌似都无法完成len([]string)的校验效果