- Created by 郭强, last modified on Dec 28, 2022
Struct
校验常使用以下链式操作方式:
g.Validator().Data(object).Run(ctx)
校验tag
规则介绍
在开始介绍Struct
参数类型校验之前,我们来介绍一下常用的校验tag
规则。规则如下:
[属性别名@]校验规则[#错误提示]
其中:
属性别名
和错误提示
为非必需字段,校验规则
是必需字段。属性别名
非必需字段,指定在校验中使用的对应struct
属性的别名,同时校验后返回的error
对象中的也将使用该别名返回。例如在处理请求表单时比较有用,因为表单的字段名称往往和struct
的属性名称不一致。大部分场景下不需要设置属性别名,默认直接使用属性名称即可。校验规则
则为当前属性的校验规则,多个校验规则请使用|
符号组合,例如:required|between:1,100
。错误提示
非必需字段,表示自定义的错误提示信息,当规则校验时对默认的错误提示信息进行覆盖。
校验tag
使用示例
package main import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" ) type User struct { Uid int `v:"uid @integer|min:1#|请输入用户ID"` Name string `v:"name @required|length:6,30#请输入用户名称|用户名称长度非法"` Pass1 string `v:"password1@required|password3"` Pass2 string `v:"password2@required|password3|same:Pass1#|密码格式不合法|两次密码不一致,请重新输入"` } func main() { var ( ctx = gctx.New() user = &User{ Name: "john", Pass1: "Abc123!@#", Pass2: "123", } ) err := g.Validator().Data(user).Run(ctx) if err != nil { g.Dump(err.Items()) } }
可以看到,我们可以对在struct
定义时使用了gvalid
的gvalid tag
来绑定校验的规则及错误提示信息。在此示例代码中,same:password1
规则同使用same:Pass1
规则是一样的效果。也就是说,在数据校验中,可以同时使用原有的struct
属性名称,也可以使用别名。但是,返回的结果中只会使用别名返回,这也是别名最大的用途。此外,在对struct
对象进行校验时,也可以传递校验或者和错误提示参数,这个时候会覆盖struct
在定义时绑定的对应参数。
以上示例执行后,输出结果为:
[ { "uid": { "min": "请输入用户ID", }, }, { "name": { "length": "用户名称长度非法", }, }, { "password2": { "password3": "密码格式不合法", }, }, ]
使用map
指定校验规则
package main import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" ) func main() { type User struct { Age int Name string } var ( ctx = gctx.New() user = User{Name: "john"} rules = map[string]string{ "Name": "required|length:6,16", "Age": "between:18,30", } messages = map[string]interface{}{ "Name": map[string]string{ "required": "名称不能为空", "length": "名称长度为{min}到{max}个字符", }, "Age": "年龄为18到30周岁", } ) err := g.Validator().Rules(rules).Messages(messages).Data(user).Run(ctx) if err != nil { g.Dump(err.Maps()) } }
在以上示例中,Age
属性由于默认值0
的存在,因此会引起required
规则的失效,因此这里没有使用required
规则而是使用between
规则来进行校验。示例代码执行后,终端输出:
{ "Age": { "between": "年龄为18到30周岁" }, "Name": { "length": "名称长度为6到16个字符" } }
结构体递归校验(嵌套校验)
支持递归的结构体校验(嵌套校验),即如果属性也是结构体(也支持嵌套结构体(embedded
)),那么将会自动将该属性执行递归校验。使用示例:
package main import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" ) func main() { type Pass struct { Pass1 string `v:"password1@required|same:password2#请输入您的密码|您两次输入的密码不一致"` Pass2 string `v:"password2@required|same:password1#请再次输入您的密码|您两次输入的密码不一致"` } type User struct { Pass Id int Name string `valid:"name@required#请输入您的姓名"` } var ( ctx = gctx.New() user = &User{ Name: "john", Pass: Pass{ Pass1: "1", Pass2: "2", }, } ) err := g.Validator().Data(user).Run(ctx) g.Dump(err.Maps()) }
或者属性为嵌套结构体(embedded
)的场景:
package main import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" ) func main() { type Pass struct { Pass1 string `v:"password1@required|same:password2#请输入您的密码|您两次输入的密码不一致"` Pass2 string `v:"password2@required|same:password1#请再次输入您的密码|您两次输入的密码不一致"` } type User struct { Id int Name string `valid:"name@required#请输入您的姓名"` Pass Pass } var ( ctx = gctx.New() user = &User{ Name: "john", Pass: Pass{ Pass1: "1", Pass2: "2", }, } ) err := g.Validator().Data(user).Run(ctx) g.Dump(err.Maps()) }
执行后,终端输出:
{ "password1": { "same": "您两次输入的密码不一致", }, "password2": { "same": "您两次输入的密码不一致", }, }
更多递归校验的介绍,请参考章节:数据校验-递归校验
Content Menu
- No labels
8 Comments
一枚大叔
多个验证规则,如何只定义一个错误提示?让定义的规则都提示这一个错误信息,不需要每个规则都定义错误提示信息。
糖水不加糖
写个后置中间判断error是否是validate的 然后改写返回的message
hanwei
结构体校验为什么返回的是title字段不能为空,而不是标题不能为空
type MenuMeta struct {
Title string `json:"title" v:"required" dc:"标题"`
FrameSrc string `json:"frameSrc" dc:"内嵌地址"`
Icon int `json:"icon" v:"required" dc:"图标"`
Hidden bool `json:"showLink" dc:"是否隐藏"`
ShowParent bool `json:"showParent" dc:"是否显示父级菜单"`
KeepAlive bool `json:"keepAlive" dc:"路由组件缓存"`
FrameLoading bool `json:"frameLoading" dc:"内嵌加载动画"`
}
糖水不加糖
写上对应规则的失败消息
hanwei
不能设置一个字段的label,后续验证是label+错误提示吗? 如果每个添加中文注释,这不是显得tag的内容很长了吗
糖水不加糖
你可以查看下源码找下有没有对应的set方法
hanwei
没有找到类似的,但还是谢谢你的回答吧
叮当猫
感觉Rules、Data、Assoc这3个函数的功能是一样的,它们的参数互换,基本都能得到一样的结果