Checker
是Golang的参数校验的包,用于结构体或者非结构的参数校验,包括结构体中不同字段比较的校验,Slice/Array/Map中的元素校验,还提供自定义的校验规则。
Go 1.13 或以上.
go get -u github.com/liangyaopei/checker
使用Add
添加规则时,fieldExpr
有三种情况:
fieldExpr
为空字符串,这时会直接校验值。fieldExpr
为单个字段,这时会先取字段的值,再校验。fieldExpr
为点(.)分割的字段,先按照.
的层级关系取值,再校验。
按字段取值时,如果字段是指针,就取指针的值校验;如果是空指针,则视为没有通过校验。
如果需要判断空指针,可以使用特殊的规则Nil
。
来自checker_test.go
的例子:
// Item.Email需要符合电子邮箱的格式
type Item struct {
Info typeInfo
Email string
}
type typeStr string
// Item.Info.Type = "range",typeInfo.Type的长度为2,元素都是格式符合"2006-01-02"
// Item.Info.Type = "last",typeInfo.Type的长度为1,元素是正整数,Granularity只能是day/week/month之一
type typeInfo struct {
Type typeStr
Range []string
Unit string
Granularity string
}
// 规则如下
rule := And(
Email("Email"),
Field("Info",
Or(
And(
EqStr("Type", "range"),
Length("Range", 2, 2),
Array("Range", isDatetime("", "2006-01-02")),
),
And(
EqStr("Type", "last"),
InStr("Granularity", "day", "week", "month"),
Number("Unit"),
),
),
),
)
itemChecker := NewChecker()
// 校验参数
itemChecker.Add(rule, "wrong item")
需要注意的是,不同的规则树,可以产生相同的校验规则,上面的rule
可以改写成:
rule := And(
Email("Email"),
Or(
And(
EqStr("Info.Type", "range"),
Length("Info.Range", 2, 2),
Array("Info.Range", Time("", "2006-01-02")),
),
And(
EqStr("Info.Type", "last"),
InStr("Info.Granularity", "day", "week", "month"),
Number("Info.Unit"),
),
),
)
尽管规则树不一样,但是树的叶子节点的fieldExpr
是一样的(这可以缓存字段),校验逻辑也是一样的。
Rule
是一个接口,它有很多的实现。Rule
的实现可以分为复合规则和单个规则。
复合规则包含其他的规则。
名字 | 作用 |
---|---|
Field(fieldExpr string, rule Rule) Rule |
对字段使用rule 校验 |
And(rules ...Rule) Rule |
需要所有的规则都通过 |
Or(rules ...Rule) Rule |
需要由一个规则通过 |
Not(innerRule Rule) Rule |
对规则取反 |
Array(fieldExpr string, innerRule Rule) Rule |
对数组的每一个元素使用规则 |
Map(fieldExpr string, keyRule Rule, valueRule Rule) Rule |
对map的key/value使用keyRule和valueRule进行校验 |
单个规则可分为比较型,枚举型,格式型等。
比较型规则分为单个字段比较规则,多个字段比较规则。
单个字段比较规则包括:
名字 |
---|
EqInt(filedExpr string, equivalent int) Rule |
NeInt(filedExpr string, inequivalent int) Rule |
RangeInt(filedExpr string, ge int, le int) Rule |
以及uint
, string
,float
,time.Time
, Comparable
的实现。
多个字段比较规则
名字 |
---|
CrossComparable(fieldExprLeft string, fieldExprRight string, op operand) Rule |
fieldExprLeft
,fieldExprRight
用来定位参加比较的字段,op
是运算操作符,包括相等/不等/大于等。
``CrossComparable支持的字段类型包括
int``uint``float``string``time.Time``Comparable`。
枚举型包括
名字 |
---|
InStr(filedExpr string, enum ...string) Rule |
InInt(filedExpr string, enum ...int) Rule |
InUint(filedExpr string, enum ...uint) Rule |
InFloat(filedExpr string, enum ...float64) Rule |
格式型规则包括
名字 |
---|
Email(fieldExpr string) Rule |
Number(fieldExpr string) Rule |
URL(fieldExpr string) Rule |
Ip(fieldExpr string) Rule |
等等
除了以上已有规则,用户还可以使用把校验函数传给Custom
,实现自定义规则,参考例子.
Checker
是一个接口
Add(rule Rule, prompt string)
: 添加规则,和没有通过规则是的错误提示。Check(param interface{}) (bool, string, string)
: 校验参数,依次返回是否通过校验,错误提示,错误日志。错误日志包含哪个字段没有通过哪个规则的信息。
定义规则时,还可以定义规则没有通过时的错误提示,例子
rule := checker.And(
checker.Email("Email").Prompt("Wrong email format") // [1],
checker.And(
checker.EqStr("Info.Type", "range"),
checker.Length("Info.Range", 2, 2).Prompt("Range's length should be 2") // [2],
checker.Array("Info.Range", checker.Time("", "2006-01-02")).
Prompt("Range's element should be time format") // [3],
),
)
validator := checker.NewChecker()
validator.Add(rule, "wrong parameter") // [4]
isValid, prompt, errMsg := validator.Check(item)
当规则没有通过时,会优先返回规则自己的prompt(代码的[1]/[2]/[3]),如果规则没有自己的prompt, 就会返回添加规则时的prompt(代码中的[4])。
当规则没有通过时,errMsg
是错误日志,用来定位出错的字段,参见例子。
从上面的规则树图示,可以看到,如果具有相同的字段表达式的叶子节点需要被多次校验, 可以将这个叶子节点的表达式的值缓存下来,减少反射调用的开销。