编写GO的WEB开发框架 (六): Validator数据校验

元气小坏坏 提交于 2020-03-25 03:52:19

3 月,跳不动了?>>>

一般地,获取到请求参数后,都需要根椐接口定义,对参数有一些合法性检查,比如:

  • 是否必填
  • 是否数字,数字的范围
  • 字符串的长度
  • 值是否在指定的列表中
  • 是否有效的日期
  • 是否满足指定的正式表达式

本篇讲述怎么编写一个Validator来对请求参数进行合法性检查。

validator的使用方法

设计一个功能时,我都习惯“目标驱动”,那就先来看看我期望的Validator怎么使用

func (this *Controller) User(){
	validator:=NewValidator(this.Post) //将要检查的数据字典传入,生成Validator对象
	validator.AddRule("name","string","2-5",true) //对字段name添加规则: 2-5个字符长度,必填
	validator.AddRule("sport","list","football,swim",false) //对字段sport添加规则: 值需在列表中(football,swim),非必填
	...
	if err:= validator.Check();err !=nil{
		//检查不通过,处理错误 
	}
}

相关结构、接口及实现

有了目标,就开始定义对象、接口及相关的方法

type Validator struct {
	data map[string]string //要校验的数据字典
	rule map[string]*vRule //规则列表,key为字段名
}
type vRule struct {
	vr       ValidateRuler
	required bool
}
//校验规则接口,支持自定义规则
type ValidateRuler interface {
	Check(data string) error
}
//内置规则结构,实现ValidateRuler接口
type normalRule struct {
	key    string
	rule   string
	params string
}
//创建校验器对象
func NewValidator(data map[string]string) *Validator {
	v := &Validator{data: data}
	v.rule = make(map[string]*vRule)
	return v
}

//添加内置的校验规则(同一个key只能有一条规则,重复添加会覆盖)
func (this *Validator) AddRule(key string, rule string, params string, required ...bool) {
	nr := &normalRule{key, rule, params}
	this.rule[key] = &vRule{nr, true} //默认required = true
	if len(required) > 0 {
		this.rule[key].required = required[0]
	}
}

//框架不可能包括所有的规则,为了满足不同应用的需要,除了内置规则外,需同时支持自定义规则的添加。
//go不支持重载,所以定义一个新方法来添加自定义规则(使用ValidateRuler interface参数)
func (this *Validator) AddExtRule(key string, rule ValidateRuler, required ...bool) {
	this.rule[key] = &vRule{rule, true}
	if len(required) > 0 {
		this.rule[key].required = required[0]
	}
}

执行检查

//执行检查
func (this *Validator) Check() (errs map[string]error) {
	errs = make(map[string]error)
	for k, v := range this.rule {
		data, exists := this.data[k]
		if !exists { //无值
			if v.required { //如果必填,报错
				errs[k] = errors.New("data error: required field miss")
			}
		} else { //有值判断规则
			if err := v.vr.Check(data); err != nil { //调用ValidateRuler接口的Check方法来检查
				errs[k] = err
			}
		}
	}
	return errs
}

内置规则实现ValidateRuler接口

接下来,编写normalRule的Check方法,以实现ValidateRuler接口

func (this *normalRule) Check(data string) (Err error) {
	if this.params == "" {
		Err = errors.New("rule error: params wrong of rule")
		return
	}
	switch this.rule {
	case "string":
		//字符串,根椐params判断长度的最大值和最小值
	case "number":
		//判断是否整数数字
		//判断最大值和最小值是否在params指定的范围
	case "list":
		//判断值是否在params指定的列表
	case "regular":
		//是否符合正则表达式
	default:
		Err = errors.New(fmt.Sprintf("rule error: not support of rule=%s", this.rule))
	}
	return
}

使用自定义规则

当内置规则不满足时,开发者可以自定义规则来检查,只需规则实现了ValidateRuler 接口即可

type myRuler struct{
}
//添加Check方法,实现ValidateRuler 接口
func (this *myRuler) Check(data string)(Err error){
	//判断data是否符合规则
}
//添加规则
validator.AddExtRule("name", &myRuler{})
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!