// Package apollo... // // Description : apollo... // // Author : go_developer@163.com<白茶清欢> // // Date : 2021-11-24 10:26 下午 package apollo import ( "encoding/json" "errors" "fmt" "regexp" "strings" "sync" "git.zhangdeman.cn/zhangdeman/gopkg/convert" "git.zhangdeman.cn/zhangdeman/gopkg/util" ) const ( // OperateTypeIs 固定值 OperateTypeIs = "is" // OperateTypeIn 在指定枚举值中 OperateTypeIn = "in" // OperateTypeNotIn 不在指定枚举值中 OperateTypeNotIn = "not_in" // OperateGt 大于 OperateGt = "gt" // OperateGte 大于等于 OperateGte = "gte" // OperateLt 小于 OperateLt = "lt" // OperateLte 小于等于 OperateLte = "lte" // OperateTypeContains 包含 OperateTypeContains = "contains" // OperateTypeRegular 正则匹配 OperateTypeRegular = "regular" ) var ( // hasCompilerRegula 已编译正则,不进行重复编辑 hasCompilerRegula map[string]*regexp.Regexp // regulaLock 编译正则用的锁 regulaLock *sync.RWMutex ) func init() { regulaLock = &sync.RWMutex{} hasCompilerRegula = make(map[string]*regexp.Regexp) } // Rule 数据过滤规则 // // Author : go_developer@163.com<白茶清欢> // // Date : 10:32 下午 2021/11/24 type Rule struct { Name string `json:"name"` // 规则名称 ConditionList []Condition `json:"condition_list"` // 条件列表 Data map[string]interface{} `json:"data"` // 满足条件时返回的数据 } // Condition 条件处理 // // Author : go_developer@163.com<白茶清欢> // // Date : 10:27 下午 2021/11/24 type Condition struct { InputKey string `json:"input_key"` // 从输入数据中读取的key Operate string `json:"operate"` // 操作 TargetValue string `json:"target_value"` // 目标值 } // Search 搜索key并按照指定条件过滤 // // Author : go_developer@163.com<白茶清欢> // // Date : 11:01 下午 2021/11/24 func Search(key string, inputData map[string]interface{}, receiver interface{}) error { if nil == receiver { return errors.New("receiver is nil") } if nil == inputData { inputData = make(map[string]interface{}) } var ( readResult string err error formatResult []Rule ) if readResult = Client.GetStringValue(key, ""); len(readResult) == 0 { return errors.New("key is not found : " + key) } if err = json.Unmarshal([]byte(readResult), &formatResult); nil != err { return errors.New("parse read config fail : " + err.Error()) } for _, rule := range formatResult { if checkRule(rule, inputData) { byteData, mErr := json.Marshal(rule.Data) if nil != mErr { return mErr } // 命中规则, 返回数据 return util.JSONUnmarshalWithNumber(byteData, receiver) } } return nil } // checkRule 检测数据是否命中规则 // // Author : go_developer@163.com<白茶清欢> // // Date : 10:59 下午 2021/11/24 func checkRule(rule Rule, inputData map[string]interface{}) bool { for _, cond := range rule.ConditionList { val, exist := inputData[cond.InputKey] if !exist { // 输入的key 不存在, 不符合规则 return false } switch cond.Operate { case OperateTypeIs: if !is(val, cond.TargetValue) { return false } case OperateTypeIn: if !in(val, cond.TargetValue) { return false } case OperateTypeNotIn: if !notIn(val, cond.TargetValue) { return false } case OperateTypeContains: if !contains(val, cond.TargetValue) { return false } case OperateGt: if !compareNumber(val, cond.TargetValue, OperateGt) { return false } case OperateGte: if !compareNumber(val, cond.TargetValue, OperateGte) { return false } case OperateLt: if !compareNumber(val, cond.TargetValue, OperateLt) { return false } case OperateLte: if !compareNumber(val, cond.TargetValue, OperateLte) { return false } default: return false } } return true } // is 判断是否相等 // // Author : go_developer@163.com<白茶清欢> // // Date : 11:28 上午 2021/11/25 func is(inputVal interface{}, targetValue string) bool { return fmt.Sprintf("%v", inputVal) == targetValue } // in ... // // Author : go_developer@163.com<白茶清欢> // // Date : 11:47 上午 2021/11/25 func in(inputValue interface{}, targetValue string) bool { if nil == inputValue { return false } inputStr := fmt.Sprintf("%v", inputValue) targetList := strings.Split(targetValue, ",") for _, item := range targetList { if inputStr == item { return true } } return false } // notIn ... // // Author : go_developer@163.com<白茶清欢> // // Date : 11:47 上午 2021/11/25 func notIn(inputValue interface{}, targetValue string) bool { if nil == inputValue { return false } inputStr := fmt.Sprintf("%v", inputValue) targetList := strings.Split(targetValue, ",") for _, item := range targetList { if inputStr == item { return false } } return true } // compareNumber ... // // Author : go_developer@163.com<白茶清欢> // // Date : 11:56 上午 2021/11/25 func compareNumber(inputValue interface{}, targetValue string, operateType string) bool { if inputValue == nil || len(targetValue) == 0 { return false } var ( err error inputFloat float64 targetFloat float64 ) if err = convert.ConvertAssign(&inputFloat, inputValue); nil != err { return false } if err = convert.ConvertAssign(&targetFloat, targetValue); nil != err { return false } switch operateType { case OperateGt: return inputFloat > targetFloat case OperateGte: return inputFloat >= targetFloat case OperateLt: return inputFloat < targetFloat case OperateLte: return inputFloat <= targetFloat } return false } // contains ... // // Author : go_developer@163.com<白茶清欢> // // Date : 12:03 下午 2021/11/25 func contains(inputValue interface{}, targetValue string) bool { return strings.Contains(fmt.Sprintf("%v", inputValue), targetValue) } // regula 正则匹配 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:15 下午 2021/11/25 func regula(inputValue interface{}, targetValue string) bool { var ( reg *regexp.Regexp err error ) regulaLock.Lock() if _, exist := hasCompilerRegula[targetValue]; !exist { if reg, err = regexp.Compile(targetValue); nil != err { regulaLock.Unlock() return false } hasCompilerRegula[targetValue] = reg } else { reg = hasCompilerRegula[targetValue] } regulaLock.Unlock() // 判断是否匹配到数据 result := reg.FindAllStringSubmatch(fmt.Sprintf("%v", inputValue), -1) return len(result) > 0 }