验证器
验证器主要是为了在控制器层进行参数校验的,目前我们使用的是 gin 的验证器。gin 内部使用的包是开源的 https://github.com/go-playground/validator
。
1. 样例
比如有一个添加用户的接口,需要验证用户名必填,并且长度最大 20 个字符。
此样例仅展示了 required 和 max 验证器,更多的验证器请参考 validator 官方文档
1.1. 先定义一个结构体 p,用来接收请求的参数
type par struct {
Name string `json:"name" validate:"required,max=20" form:"name" label:"姓名"`
}
1.1.1. tag 说明
- validate 标签:yago 保留了原生的 validate 标签,替换掉了 gin 默认的 binding 标签
- json 标签:如果 Content-Type 是 application/json,gin 根据 json 标签的值来取值赋值
- form 标签:如果 Content-Type 不是 application/json,gin 根据 form 标签来取值赋值
- label 标签:是用来替换报错时的字段名信息的,上例中如果不指定默认是 Name
1.2. 使用 ShouldBind 赋值并验证
通过 ctx 的 ShouldBind 方法,将请求参数赋值给变量 p,ShouldBind 方法内部会调用 validator 包做验证 调用 ctx 的 SetError 方法,yago 会自动处理验证的错误信息,并做相应的翻译。
func (h *HomeHttp) AddAction(c *yago.Ctx) {
p := par{}
err := c.ShouldBind(&p)
if err != nil {
c.SetError(err)
return
}
// your code here
c.SetData(g.Hash{"name":p.Name})
return
}
2. 特别说明
2.1. 默认值
目前未发现 validator 包设置默认值的方法,我们可以在初始化变量时给出,如下例:
func (h *HomeHttp) ListAction(c *yago.Ctx) {
type p struct {
Q string `json:"q" validate:"omitempty" form:"q"`
Page int `json:"page" validate:"omitempty" form:"name" label:"当前页"`
Pagesize int `json:"pagesize" validate:"omitempty" form:"name" label:"页大小"`
}
// 设置默认值
pi := &p{
Page: 1,
Pagesize: 10,
}
err := c.ShouldBind(&pi)
if err != nil {
c.SetError(err)
return
}
// your code here
c.SetData(g.Hash{})
return
}
2.2. 零值问题
go 的 Struct 字段是有零值的,比如上文中 Name 字段不传,它的值就是空串,我们不能根据他是否为空串 来判断用户是否有传这个字段,那么怎么处理咧,下文给出样例
func (h *HomeHttp) AddAction(c *yago.Ctx) {
// 采用字符串指针代替字符串类型
type par struct {
Name *string `json:"name" validate:"omitempty" form:"name" label:"姓名"`
}
p := par{}
err := c.ShouldBind(&p)
if err != nil {
c.SetError(err)
return
}
// 此处可以根据 par.Name 是否为 nil 来判断用户是否有传该值
if p.Name == nil{
// 说明用户没有传
c.SetData("no name")
return
}
c.SetData(*p.Name)
return
}