返回
告别繁复 if 条件语句,一招学会规则执行器替代方案
闲谈
2024-01-08 08:31:07
最近在公司领到一个小需求,需要对之前已有的试用用户申请规则进行拓展。按照上述的条件我们可以得出的结论是:
-
咱们的主要流程主要是基于 and 或者 or 的关系。
-
基于现有的一些产品限制,我们不能使用 es 这种动态语言,也无法直接在数据库中存储复杂的 json,只能基于已有字段判断。
基于如上两个问题,我们其实可以想到,这个规则的本质就是一个树形结构,即树根为 and 或者 or,树枝是各个维度,树叶就是对应维度的值。
有了这个思路,我们就很好办了,首先给我们的规则执行器设计好接口,参数就是我们自定义的规则 json,返回值是是否满足规则。
type Validator interface {
Validate(rules interface{}) (bool, error)
}
我们定义了一个接口,用来强制要求实现这个接口的对象需要实现 Validate 函数,这个函数的参数和返回值都已经声明好了,所以我们实现这个接口的对象只需要实现 Validate 函数的具体逻辑即可。
接着我们就可以写一个默认的规则执行器了。
type DefaultValidator struct {
}
func (v *DefaultValidator) Validate(rules interface{}) (bool, error) {
ruleMap, ok := rules.(map[string]interface{})
if !ok {
return false, errors.New("rules must be a map[string]interface{}")
}
return v.validateMap(ruleMap), nil
}
func (v *DefaultValidator) validateMap(ruleMap map[string]interface{}) bool {
for k, v := range ruleMap {
switch k {
case "and":
return v.validateAnd(v.([]interface{}))
case "or":
return v.validateOr(v.([]interface{}))
default:
return false
}
}
return false
}
func (v *DefaultValidator) validateAnd(rules []interface{}) bool {
for _, rule := range rules {
ruleMap, ok := rule.(map[string]interface{})
if !ok {
return false
}
if !v.validateMap(ruleMap) {
return false
}
}
return true
}
func (v *DefaultValidator) validateOr(rules []interface{}) bool {
for _, rule := range rules {
ruleMap, ok := rule.(map[string]interface{})
if !ok {
return false
}
if v.validateMap(ruleMap) {
return true
}
}
return false
}
这个规则执行器很简单,它只实现了两种最基本的规则:and 和 or。接下来我们就可以使用这个规则执行器来处理我们的规则了。
func main() {
validator := DefaultValidator{}
rules := map[string]interface{}{
"and": []interface{}{
map[string]interface{}{
"field1": "value1",
},
map[string]interface{}{
"field2": "value2",
},
},
}
result, err := validator.Validate(rules)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(result)
}
运行这个程序,我们将会得到以下输出:
true
这表明我们的规则执行器能够正确地处理我们的规则。
规则执行器是一种强大的工具,它可以帮助我们更轻松地处理复杂的条件判断。在本文中,我们介绍了如何使用规则执行器来替代传统的 if-else 语句。我们还提供了一个简单的规则执行器实现,供您参考。希望本文对您有所帮助。