一般地,获取到请求参数后,都需要根椐接口定义,对参数有一些合法性检查,比如:
- 是否必填
- 是否数字,数字的范围
- 字符串的长度
- 值是否在指定的列表中
- 是否有效的日期
- 是否满足指定的正式表达式
本篇讲述怎么编写一个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{})
来源:oschina
链接:https://my.oschina.net/u/140753/blog/632005