引言
- 我在使用gin开发自己的框架时,发现一个痛点,就是gin的validator只能在结构体上绑定的同时校验
- 尴尬的事情是比如Model层操作这个增删改查的时候,我一个Model的结构体实现不了,我需要定义多个
- 在学习Go-Vue-Admin框架的时候我发现了,他们是自己写了一个简易的校验
- 于是我就在想可不可以基于gin自带的实现,单独定义验证规则,不需要绑定到Model的结构体
- 项目github
1、查文档
- 很遗憾,没有找到完整的中文文档,我只能看一些文章
- github找对应的demo案例
2、实现的关键
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
}
3、验证器代码 (简略)
type Rules map[string]string
// st是Model结构体 一般在 c.ShouldBind(&st) 就已经绑定值了
func Verify(st interface{}, r Rules) error {
va := global.Verify //全局变量存储的Validate
typ := reflect.TypeOf(st)
val := reflect.ValueOf(st)
kd := val.Kind()
if kd != reflect.Struct {
return errors.New("expect struct")
}
num := val.NumField()
for i := 0; i < num; i++ {
// 取每个字段
typVal := typ.Field(i)
// 获取tag
tag := typVal.Tag.Get("desc")
// 查看规则是否有该字段无则忽略
verify, ok := r[typVal.Name]
if !ok {
continue
}
// 获取字段的值信息
v := val.Field(i).Interface()
if err := va.Var(v, verify); err != nil {
var b strings.Builder
if tag != "" {
b.WriteString(tag)
} else {
b.WriteString(typVal.Name)
}
b.WriteString(GetError(err))//GetError是我处理转成中文错误信息的
return errors.New(b.String())
}
}
return nil
}
4、验证规则
放在request目录下,验证规则和
package request
var (
RuleAddVerify = Rules{"Role_name": "required", "Role_desc": "required"}
RuleUpVerify = Rules{"Authority_id": "required", "Role_name": "omitempty,required", "Role_desc": "omitempty,required"}
RuleDelVerify = Rules{"Authority_id": "required"}
)
5、案例
model结构体定义
type AdminRule struct {
CreatedOn int64 `json:"created_on"`
ModifiedOn int64 `json:"modified_on"`
DeletedAt gorm.DeletedAt `json:"deleted_at"`
Role_name string `desc:"角色名称" json:"role_name" form:"role_name" `
Role_desc string `desc:"角色描述" json:"role_desc" form:"role_desc" `
Status int `desc:"角色状态" json:"status"`
Authority_id int `desc:"角色ID" gorm:"primary_key" uri:"id" form:"id" json:"id"`
}
控制器
func CreateRule(c *gin.Context) {
var rule models.AdminRule
c.ShouldBind(&rule)//不接收gin自己的验证错误信息,只需要绑定结构体的值
//验证规则
if err := request.Verify(rule, request.RuleAddVerify); err != nil {
tool.JSONP(c, 400, err.Error(), nil)
return
}
//调用服务层
if ret := services.CreateRule(rule); !ret.GetStatus() {
tool.JSONP(c, 40001, ret.GetMsg(), ret["data"])
return
} else {
tool.JSONP(c, 0, ret.GetMsg(), ret["data"])
}
}
6、结尾
这样的写法就比较清晰了,我们只需要定义一个Model和多个验证器规则,一个接口的增删改查就比较舒服了 与诸君共勉之,写的不好的地址给指正,希望对您有帮助,思路很重要