gvalid模块实现了非常强大易用的数据校验功能,封装了40种常用的校验规则,支持单数据多规则校验、多数据多规则批量校验、自定义错误信息、自定义正则校验、支持struct tag规则及提示信息绑定等特性。

使用方式:

  1. import "gitee.com/johng/gf/g/util/gvalid"

校验规则

40种常用的校验规则:

  1. required 格式:required 说明:必需参数
  2. required-if 格式:required-if:field,value,... 说明:必需参数(当任意所给定字段值与所给值相等时,即:当field字段的值为value时,当前验证字段为必须参数)
  3. required-unless 格式:required-unless:field,value,... 说明:必需参数(当所给定字段值与所给值都不相等时,即:当field字段的值不为value时,当前验证字段为必须参数)
  4. required-with 格式:required-with:field1,field2,... 说明:必需参数(当所给定任意字段值不为空时)
  5. required-with-all 格式:required-with-all:field1,field2,... 说明:必须参数(当所给定所有字段值都不为空时)
  6. required-without 格式:required-without:field1,field2,... 说明:必需参数(当所给定任意字段值为空时)
  7. required-without-all 格式:required-without-all:field1,field2,...说明:必须参数(当所给定所有字段值都为空时)
  8. date 格式:date 说明:参数为常用日期类型,格式:2006-01-02, 20060102, 2006.01.02
  9. date-format 格式:date-format:format 说明:判断日期是否为指定的日期格式,format为Go日期格式(可以包含时间)
  10. email 格式:email 说明:EMAIL邮箱地址
  11. phone 格式:phone 说明:手机号
  12. telephone 格式:telephone 说明:国内座机电话号码,"XXXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"、"XXXXXXXX"
  13. passport 格式:passport 说明:通用帐号规则(字母开头,只能包含字母、数字和下划线,长度在6~18之间)
  14. password 格式:password 说明:通用密码(任意可见字符,长度在6~18之间)
  15. password2 格式:password2 说明:中等强度密码(在弱密码的基础上,必须包含大小写字母和数字)
  16. password3 格式:password3 说明:强等强度密码(在弱密码的基础上,必须包含大小写字母、数字和特殊字符)
  17. postcode 格式:postcode 说明:中国邮政编码
  18. id-number 格式:id-number 说明:公民身份证号码
  19. qq 格式:qq 说明:腾讯QQ号码
  20. ip 格式:ip 说明:IPv4/IPv6地址
  21. ipv4 格式:ipv4 说明:IPv4地址
  22. ipv6 格式:ipv6 说明:IPv6地址
  23. mac 格式:mac 说明:MAC地址
  24. url 格式:url 说明:URL
  25. domain 格式:domain 说明:域名
  26. length 格式:length:min,max 说明:参数长度为min到max(长度参数为整形),注意中文一个汉字占3字节
  27. min-length 格式:min-length:min 说明:参数长度最小为min(长度参数为整形),注意中文一个汉字占3字节
  28. max-length 格式:max-length:max 说明:参数长度最大为max(长度参数为整形),注意中文一个汉字占3字节
  29. between 格式:between:min,max 说明:参数大小为min到max(支持整形和浮点类型参数)
  30. min 格式:min:min 说明:参数最小为min(支持整形和浮点类型参数)
  31. max 格式:max:max 说明:参数最大为max(支持整形和浮点类型参数)
  32. json 格式:json 说明:判断数据格式为JSON
  33. integer 格式:integer 说明:整数
  34. float 格式:float 说明:浮点数
  35. boolean 格式:boolean 说明:布尔值(1,true,on,yes:true | 0,false,off,no,"":false)
  36. same 格式:same:field 说明:参数值必需与field参数的值相同
  37. different 格式:different:field 说明:参数值不能与field参数的值相同
  38. in 格式:in:value1,value2,... 说明:参数值应该在value1,value2,...中(字符串匹配)
  39. not-in 格式:not-in:value1,value2,... 说明:参数值不应该在value1,value2,...中(字符串匹配)
  40. regex 格式:regex:pattern 说明:参数值应当满足正则匹配规则pattern

校验方法

相关数据结构:

  1. // 校验错误对象
  2. type Error map[string]map[string]string

校验方法列表:

  1. func Check(val interface{}, rules string, msgs interface{}, params ...map[string]interface{}) Error
  2. func CheckMap(params map[string]interface{}, rules map[string]string, msgs ...map[string]interface{}) Error
  3. func CheckStruct(st interface{}, rules map[string]string, msgs ...map[string]interface{}) Error
  4. func SetDefaultErrorMsgs(msgs map[string]string)

Check*方法只有在返回nil的情况下,表示数据校验成功,否则返回校验出错的数据项(CheckMap)以及对应的规则和错误信息的map,具体请查看后续示例代码更容易理解。

使用示例

下面我们来举几个例子,看看如何使用gvalid来实现数据校验。

单数据校验 - Check

1、校验数据长度,使用默认的错误提示

  1. rule := "length:6,16"
  2. if e := gvalid.Check("123456", rule, nil); e != nil {
  3. fmt.Println(e.String())
  4. }
  5. if e := gvalid.Check("12345", rule, nil); e != nil {
  6. fmt.Println(e.String())
  7. }
  8. // 输出: 字段长度为6到16个字符

2、校验数据类型及大小,并且使用自定义的错误提示

  1. rule := "integer|between:6,16"
  2. msgs := "请输入一个整数|参数大小不对啊老铁"
  3. if e := gvalid.Check(5.66, rule, msgs); e != nil {
  4. _, item := e.FirstItem()
  5. fmt.Println(item)
  6. }
  7. // 输出: map[integer:请输入一个整数 between:参数大小不对啊老铁]

可以看到,多个规则以及多个自定义错误提示之间使用英文“|”号进行分割,注意自定义错误提示的顺序和多规则的顺序一一对应。msgs参数除了支持string类型以外,还支持map[string]string类型,请看以下例子:

  1. rule := "url|min-length:11"
  2. msgs := map[string]string{
  3. "url" : "请输入正确的URL地址",
  4. "minlength" : "地址长度至少为:min位"
  5. }
  6. if e := gvalid.Check("http://johngcn", rule, msgs); e != nil {
  7. _, item := e.FirstItem()
  8. fmt.Println(item)
  9. }
  10. // 输出: map[url:请输入正确的URL地址]

3、使用自定义正则校验数据格式,使用默认错误提示

  1. // 参数长度至少为6个数字或者6个字母,但是总长度不能超过16个字符
  2. rule := `regex:\d{6,}|\D{6,}|max-length:16`
  3. if e := gvalid.Check("123456", rule, nil); e != nil {
  4. _, item := e.FirstItem()
  5. fmt.Println(item)
  6. }
  7. if e := gvalid.Check("abcde6", rule, nil); e != nil {
  8. _, item := e.FirstItem()
  9. fmt.Println(item)
  10. }
  11. // 输出: map[regex:字段值不合法]

多数据校验 - CheckMap

gvalid支持对多数据进行校验,支持map和struct类型,分别使用CheckMapCheckStruct方法实现。

1、多数据多规则校验,使用默认错误提示

  1. params := map[string]interface{} {
  2. "passport" : "john",
  3. "password" : "123456",
  4. "password2" : "1234567",
  5. }
  6. rules := map[string]string {
  7. "passport" : "required|length:6,16",
  8. "password" : "required|length:6,16|same:password2",
  9. "password2" : "required|length:6,16",
  10. }
  11. if e := gvalid.CheckMap(params, rules); e != nil {
  12. gutil.Dump(e)
  13. }
  14. /*
  15. 输出:
  16. {
  17. "passport": {
  18. "length": "字段长度为6到16个字符"
  19. },
  20. "password": {
  21. "same": "字段值不合法"
  22. }
  23. }
  24. */

2、多数据多规则校验,使用自定义错误提示

  1. params := map[string]interface{} {
  2. "passport" : "john",
  3. "password" : "123456",
  4. "password2" : "1234567",
  5. }
  6. rules := map[string]string {
  7. "passport" : "required|length:6,16",
  8. "password" : "required|length:6,16|same:password2",
  9. "password2" : "required|length:6,16",
  10. }
  11. msgs := map[string]interface{} {
  12. "passport" : "账号不能为空|账号长度应当在:min到:max之间",
  13. "password" : map[string]string {
  14. "required" : "密码不能为空",
  15. "same" : "两次密码输入不相等",
  16. },
  17. }
  18. if e := gvalid.CheckMap(params, rules, msgs); e != nil {
  19. gutil.Dump(e)
  20. }
  21. /*
  22. 输出:
  23. {
  24. "passport": {
  25. "length": "账号长度应当在6到16之间"
  26. },
  27. "password": {
  28. "same": "两次密码输入不相等"
  29. }
  30. }
  31. */

该示例同时也展示了自定义错误传递的两种数据类型,string或者map[string]string。其中map[string]string类型参数需要指定对应字段、对应规则的错误提示信息,是一个二维的“关联数组”。

多数据校验 - CheckStruct

CheckStruct的使用方式同CheckMap,除了第一个参数为struct类型的对象(也可以是对象指针)。但是需要注意的一个细节是,struct的属性会有默认值,因此某些情况下会引起required规则的失效,因此根据实际情况配合多种规则一起校验会是一个比较严谨的做法。

示例1,使用map指定规则及提示信息

  1. type Object struct {
  2. Name string
  3. Age int
  4. }
  5. rules := map[string]string {
  6. "Name" : "required|length:6,16",
  7. "Age" : "between:18,30",
  8. }
  9. msgs := map[string]interface{} {
  10. "Name" : map[string]string {
  11. "required" : "名称不能为空",
  12. "length" : "名称长度为:min到:max个字符",
  13. },
  14. "Age" : "年龄为18到30周岁",
  15. }
  16. obj := Object{Name : "john"}
  17. // 也可以是指针
  18. // obj := &Object{Name : "john"}
  19. if e := gvalid.CheckStruct(obj, rules, msgs); e != nil {
  20. gutil.Dump(e)
  21. }
  22. /*
  23. 输出:
  24. {
  25. "Age": {
  26. "between": "年龄为18到30周岁"
  27. },
  28. "Name": {
  29. "length": "名称长度为6到16个字符"
  30. }
  31. }
  32. */

在以上示例中,Age属性由于默认值0的存在,因此会引起required规则的失效,因此这里没有使用required规则而是使用between规则来进行校验。

示例2,使用struct tag绑定规则及提示信息

  1. package main
  2. import (
  3. "gitee.com/johng/gf/g/util/gutil"
  4. "gitee.com/johng/gf/g/util/gvalid"
  5. )
  6. type User struct {
  7. Uid int `gvalid:"uid @integer|min:1"`
  8. Name string `gvalid:"name @required|length:6,30#请输入用户名称|用户名称长度非法"`
  9. Pass1 string `gvalid:"password1@required|password3"`
  10. Pass2 string `gvalid:"password2@required|password3|same:password1#||两次密码不一致,请重新输入"`
  11. }
  12. func main() {
  13. user := &User{
  14. Name : "john",
  15. Pass1: "Abc123!@#",
  16. Pass2: "123",
  17. }
  18. // 使用结构体定义的校验规则和错误提示进行校验
  19. gutil.Dump(gvalid.CheckStruct(user, nil))
  20. // 自定义校验规则和错误提示,对定义的特定校验规则和错误提示进行覆盖
  21. rules := map[string]string {
  22. "Uid" : "required",
  23. }
  24. msgs := map[string]interface{} {
  25. "Pass2" : map[string]string {
  26. "password3" : "名称不能为空",
  27. },
  28. }
  29. gutil.Dump(gvalid.CheckStruct(user, rules, msgs))
  30. }

可以看到,我们可以对在struct定义时使用了gvalid的标签属性来绑定校验的规则及错误提示信息,该标签规则如下:

  1. [属性别名@]校验规则[#错误提示]

其中,属性别名和错误提示为非必需字段。属性别名指定在校验中使用的对应struct属性的别名,同时校验成功后的map中的也将使用该别名返回,例如在处理请求表单时比较有用,因为表单的字段名称往往和struct的属性名称不一致;校验规则是必需参数,具体请查看本章节上面的相关说明;错误提示表示自定义的错误提示信息,当规则校验时对默认的错误提示信息进行覆盖。

在此示例代码中,same:password1规则同使用same:Pass2规则是一样的效果。也就是说,在数据校验中,可以同时使用原有的struct属性名称,也可以使用别名。但是,返回的结果中只会使用别名返回,这也是别名最大的用途。

此外,在使用CheckStruct方法对struct对象进行校验时,也可以传递校验或者和错误提示参数,这个时候会覆盖struct在定义时绑定的对应参数。

以上示例执行后,输出结果为:

  1. {
  2. "name": {
  3. "length": "字段长度为6到30个字符"
  4. },
  5. "password2": {
  6. "password3": "密码格式不合法,密码格式为任意6-18位的可见字符,必须包含大小写字母、数字和特殊字符",
  7. "same": "字段值不合法"
  8. }
  9. }
  10. {
  11. "name": {
  12. "length": "字段长度为6到30个字符"
  13. },
  14. "password2": {
  15. "password3": "密码格式不合法,密码格式为任意6-18位的可见字符,必须包含大小写字母、数字和特殊字符",
  16. "same": "字段值不合法"
  17. }
  18. }

错误提示

任何时候,我们都可以通过gvalid.SetDefaultErrorMsgs方法来批量设置默认的错误提示信息(特别是针对多语言环境中),但是需要注意的是,修改是全局变化的,请注意可能会对其他模块校验信息的影响。通常建议为针对特定的校验单独配置不同的校验错误提示信息。默认的错误提示如下:

  1. var defaultMessages = map[string]string {
  2. "required" : "字段不能为空",
  3. "required-if" : "字段不能为空",
  4. "required-unless" : "字段不能为空",
  5. "required-with" : "字段不能为空",
  6. "required-with-all" : "字段不能为空",
  7. "required-without" : "字段不能为空",
  8. "required-without-all" : "字段不能为空",
  9. "date" : "日期格式不正确",
  10. "date-format" : "日期格式不正确",
  11. "email" : "邮箱地址格式不正确",
  12. "phone" : "手机号码格式不正确",
  13. "telephone" : "电话号码格式不正确",
  14. "passport" : "账号格式不合法,必需以字母开头,只能包含字母、数字和下划线,长度在6~18之间",
  15. "password" : "密码格式不合法,密码格式为任意6-18位的可见字符",
  16. "password2" : "密码格式不合法,密码格式为任意6-18位的可见字符,必须包含大小写字母和数字",
  17. "password3" : "密码格式不合法,密码格式为任意6-18位的可见字符,必须包含大小写字母、数字和特殊字符",
  18. "postcode" : "邮政编码不正确",
  19. "id-number" : "身份证号码不正确",
  20. "qq" : "QQ号码格式不正确",
  21. "ip" : "IP地址格式不正确",
  22. "ipv4" : "IPv4地址格式不正确",
  23. "ipv6" : "IPv6地址格式不正确",
  24. "mac" : "MAC地址格式不正确",
  25. "url" : "URL地址格式不正确",
  26. "domain" : "域名格式不正确",
  27. "length" : "字段长度为:min到:max个字符",
  28. "min-length" : "字段最小长度为:min",
  29. "max-length" : "字段最大长度为:max",
  30. "between" : "字段大小为:min到:max",
  31. "min" : "字段最小值为:min",
  32. "max" : "字段最大值为:max",
  33. "json" : "字段应当为JSON格式",
  34. "xml" : "字段应当为XML格式",
  35. "array" : "字段应当为数组",
  36. "integer" : "字段应当为整数",
  37. "float" : "字段应当为浮点数",
  38. "boolean" : "字段应当为布尔值",
  39. "same" : "字段值不合法",
  40. "different" : "字段值不合法",
  41. "in" : "字段值不合法",
  42. "not-in" : "字段值不合法",
  43. "regex" : "字段值不合法",
  44. }