You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
5.6 KiB
207 lines
5.6 KiB
package utils
|
|
|
|
import (
|
|
"errors"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type Rules map[string][]string
|
|
|
|
type RulesMap map[string]Rules
|
|
|
|
var CustomizeMap = make(map[string]Rules)
|
|
|
|
// 注册自定义规则方案建议在路由初始化层即注册
|
|
func RegisterRule(key string, rule Rules) (err error) {
|
|
if CustomizeMap[key] != nil {
|
|
return errors.New(key + "已注册,无法重复注册")
|
|
} else {
|
|
CustomizeMap[key] = rule
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// 非空 不能为其对应类型的0值
|
|
func NotEmpty() string {
|
|
return "notEmpty"
|
|
}
|
|
|
|
// 小于入参(<) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
|
func Lt(mark string) string {
|
|
return "lt=" + mark
|
|
}
|
|
|
|
// 小于等于入参(<=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
|
func Le(mark string) string {
|
|
return "le=" + mark
|
|
}
|
|
|
|
// 等于入参(==) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
|
func Eq(mark string) string {
|
|
return "eq=" + mark
|
|
}
|
|
|
|
// 不等于入参(!=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
|
func Ne(mark string) string {
|
|
return "ne=" + mark
|
|
}
|
|
|
|
// 大于等于入参(>=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
|
func Ge(mark string) string {
|
|
return "ge=" + mark
|
|
}
|
|
|
|
// 大于入参(>) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
|
func Gt(mark string) string {
|
|
return "gt=" + mark
|
|
}
|
|
|
|
// 校验方法 接收两个参数 入参实例,规则map
|
|
func Verify(st interface{}, roleMap Rules) (err error) {
|
|
compareMap := map[string]bool{
|
|
"lt": true,
|
|
"le": true,
|
|
"eq": true,
|
|
"ne": true,
|
|
"ge": true,
|
|
"gt": true,
|
|
}
|
|
|
|
typ := reflect.TypeOf(st)
|
|
val := reflect.ValueOf(st) // 获取reflect.Type类型
|
|
|
|
kd := val.Kind() // 获取到st对应的类别
|
|
if kd != reflect.Struct {
|
|
return errors.New("expect struct")
|
|
}
|
|
num := val.NumField()
|
|
// 遍历结构体的所有字段
|
|
for i := 0; i < num; i++ {
|
|
tagVal := typ.Field(i)
|
|
val := val.Field(i)
|
|
if len(roleMap[tagVal.Name]) > 0 {
|
|
for _, v := range roleMap[tagVal.Name] {
|
|
switch {
|
|
case v == "notEmpty":
|
|
if isBlank(val) {
|
|
return errors.New(tagVal.Name + "值不能为空")
|
|
}
|
|
case compareMap[strings.Split(v, "=")[0]]:
|
|
if !compareVerify(val, v) {
|
|
return errors.New(tagVal.Name + "长度或值不在合法范围," + v)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 长度和数字的校验方法 根据类型自动校验
|
|
func compareVerify(value reflect.Value, VerifyStr string) bool {
|
|
switch value.Kind() {
|
|
case reflect.String, reflect.Slice, reflect.Array:
|
|
return compare(value.Len(), VerifyStr)
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
return compare(value.Uint(), VerifyStr)
|
|
case reflect.Float32, reflect.Float64:
|
|
return compare(value.Float(), VerifyStr)
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return compare(value.Int(), VerifyStr)
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// 非空校验
|
|
func isBlank(value reflect.Value) bool {
|
|
switch value.Kind() {
|
|
case reflect.String:
|
|
return value.Len() == 0
|
|
case reflect.Bool:
|
|
return !value.Bool()
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return value.Int() == 0
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
return value.Uint() == 0
|
|
case reflect.Float32, reflect.Float64:
|
|
return value.Float() == 0
|
|
case reflect.Interface, reflect.Ptr:
|
|
return value.IsNil()
|
|
}
|
|
return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface())
|
|
}
|
|
|
|
func compare(value interface{}, VerifyStr string) bool {
|
|
VerifyStrArr := strings.Split(VerifyStr, "=")
|
|
val := reflect.ValueOf(value)
|
|
switch val.Kind() {
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
VInt, VErr := strconv.ParseInt(VerifyStrArr[1], 10, 64)
|
|
if VErr != nil {
|
|
return false
|
|
}
|
|
switch {
|
|
case VerifyStrArr[0] == "lt":
|
|
return val.Int() < VInt
|
|
case VerifyStrArr[0] == "le":
|
|
return val.Int() <= VInt
|
|
case VerifyStrArr[0] == "eq":
|
|
return val.Int() == VInt
|
|
case VerifyStrArr[0] == "ne":
|
|
return val.Int() != VInt
|
|
case VerifyStrArr[0] == "ge":
|
|
return val.Int() >= VInt
|
|
case VerifyStrArr[0] == "gt":
|
|
return val.Int() > VInt
|
|
default:
|
|
return false
|
|
}
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
VInt, VErr := strconv.Atoi(VerifyStrArr[1])
|
|
if VErr != nil {
|
|
return false
|
|
}
|
|
switch {
|
|
case VerifyStrArr[0] == "lt":
|
|
return val.Uint() < uint64(VInt)
|
|
case VerifyStrArr[0] == "le":
|
|
return val.Uint() <= uint64(VInt)
|
|
case VerifyStrArr[0] == "eq":
|
|
return val.Uint() == uint64(VInt)
|
|
case VerifyStrArr[0] == "ne":
|
|
return val.Uint() != uint64(VInt)
|
|
case VerifyStrArr[0] == "ge":
|
|
return val.Uint() >= uint64(VInt)
|
|
case VerifyStrArr[0] == "gt":
|
|
return val.Uint() > uint64(VInt)
|
|
default:
|
|
return false
|
|
}
|
|
case reflect.Float32, reflect.Float64:
|
|
VFloat, VErr := strconv.ParseFloat(VerifyStrArr[1], 64)
|
|
if VErr != nil {
|
|
return false
|
|
}
|
|
switch {
|
|
case VerifyStrArr[0] == "lt":
|
|
return val.Float() < VFloat
|
|
case VerifyStrArr[0] == "le":
|
|
return val.Float() <= VFloat
|
|
case VerifyStrArr[0] == "eq":
|
|
return val.Float() == VFloat
|
|
case VerifyStrArr[0] == "ne":
|
|
return val.Float() != VFloat
|
|
case VerifyStrArr[0] == "ge":
|
|
return val.Float() >= VFloat
|
|
case VerifyStrArr[0] == "gt":
|
|
return val.Float() > VFloat
|
|
default:
|
|
return false
|
|
}
|
|
default:
|
|
return false
|
|
}
|
|
}
|