利用govaluate构建规则配置引擎

Govaluate简介

Govaluate 是一个 Go 语言的表达式评估库,允许你在运行时动态评估字符串表达式。虽然它不是一个完整的规则引擎,但可以用于实现一些简单的规则评估功能。

以下是一个简单示例,展示如何使用 Govaluate:

首先,你需要导入 Govaluate 库:

go 复制代码
import "github.com/Knetic/govaluate"

然后,你可以编写代码进行表达式评估:

go 复制代码
package main

import (
    "fmt"
    "github.com/Knetic/govaluate"
)

func main() {
    // 准备表达式
    expression, err := govaluate.NewEvaluableExpression("value > 10")
    if err != nil {
        fmt.Println("Error creating expression:", err)
        return
    }
    
    // 准备数据
    parameters := map[string]interface{}{
        "value": 15,
    }
    
    // 评估表达式
    result, err := expression.Evaluate(parameters)
    if err != nil {
        fmt.Println("Error evaluating expression:", err)
        return
    }
    
    // 输出评估结果
    fmt.Println("Expression evaluation result:", result)
}

在这个示例中,我们创建了一个简单的表达式 value > 10,然后使用 Govaluate 对其进行评估。我们还准备了一个包含了参数 "value"parameters 映射,其中的值是 15。最后,我们输出了表达式的评估结果。

Govaluate 提供了一种简单而灵活的方法来进行表达式评估,可以用于实现一些基本的规则评估功能。但是,如果你需要更复杂的规则引擎功能,可能需要考虑使用其他专门的规则引擎库。

除了 Govaluate 之外,还有一些其他的表达式评估库,虽然它们没有 Govaluate 那么流行,但它们提供了更多功能和更完整的支持。

自定义函数

go 复制代码
	functions := map[string]govaluate.ExpressionFunction{
		"strlen": func(args ...interface{}) (interface{}, error) {
			str, ok := args[0].(string)
			if !ok {
				return nil, fmt.Errorf("strlen function requires a string argument")
			}
			length := len(str)
			return float64(length), nil // 返回字符串的长度和 nil 错误
		},
	}

	// 定义表达式字符串
	exprString := "strlen('teststringdsa') > 10"

	// 创建可评估的表达式
	expr, err := govaluate.NewEvaluableExpressionWithFunctions(exprString, functions)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// 执行表达式
	result, err := expr.Evaluate(nil)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	fmt.Println(result)

语法

govaluate 是一个支持基本数学和逻辑运算的表达式求值器。默认情况下,它支持以下语法

基本运算符

  • + 加法
  • - 减法
  • * 乘法
  • / 除法
  • % 取模
  • ^ 幂运算

比较运算符

  • == 等于
  • != 不等于
  • < 小于
  • > 大于
  • <= 小于等于
  • >= 大于等于

逻辑运算符

  • && 逻辑与
  • || 逻辑或
  • ! 逻辑非

其他

  • 括号 () 用于改变运算优先级
  • 数字和字符串常量

这些是 govaluate 默认支持的主要语法。但是,我们可以通过自定义函数来扩展其功能,以支持更复杂的表达式。

自定义函数

我们可以考虑把go语言中自带的库集成进去,例如,下面是数据函数库

go 复制代码
package method

import (
	"fmt"
	"math"
)

// Abs 返回 x 的绝对值
func Abs(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Abs function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Abs(x), nil
}

// Ceil 返回不小于 x 的最小整数值,即向上取整
func Ceil(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Ceil function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Ceil(x), nil
}

// Floor 返回不大于 x 的最大整数值,即向下取整
func Floor(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Floor function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Floor(x), nil
}

// Max 返回 x 和 y 中的最大值
func Max(args ...interface{}) (interface{}, error) {
	if len(args) != 2 {
		return nil, fmt.Errorf("Max function requires 2 arguments")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("arguments must be float64")
	}
	y, ok := args[1].(float64)
	if !ok {
		return nil, fmt.Errorf("arguments must be float64")
	}
	return math.Max(x, y), nil
}

// Min 返回 x 和 y 中的最小值
func Min(args ...interface{}) (interface{}, error) {
	if len(args) != 2 {
		return nil, fmt.Errorf("Min function requires 2 arguments")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("arguments must be float64")
	}
	y, ok := args[1].(float64)
	if !ok {
		return nil, fmt.Errorf("arguments must be float64")
	}
	return math.Min(x, y), nil
}

// Pow 返回 x 的 y 次幂的值
func Pow(args ...interface{}) (interface{}, error) {
	if len(args) != 2 {
		return nil, fmt.Errorf("Pow function requires 2 arguments")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("arguments must be float64")
	}
	y, ok := args[1].(float64)
	if !ok {
		return nil, fmt.Errorf("arguments must be float64")
	}
	return math.Pow(x, y), nil
}

// Sqrt 返回 x 的平方根
func Sqrt(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Sqrt function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Sqrt(x), nil
}

// Round 返回最接近 x 的整数,四舍五入
func Round(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Round function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Round(x), nil
}

// Trunc 返回 x 的整数部分,舍弃小数部分
func Trunc(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Trunc function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Trunc(x), nil
}

// Sin 返回 x 的正弦值
func Sin(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Sin function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Sin(x), nil
}

// Cos 返回 x 的余弦值
func Cos(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Cos function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Cos(x), nil
}

// Tan 返回 x 的正切值
func Tan(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Tan function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Tan(x), nil
}

// Asin 返回 x 的反正弦值
func Asin(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Asin function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Asin(x), nil
}

// Acos 返回 x 的反余弦值
func Acos(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Acos function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Acos(x), nil
}

// Atan 返回 x 的反正切值
func Atan(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Atan function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Atan(x), nil
}

// Atan2 返回点 (y, x) 的反正切值
func Atan2(args ...interface{}) (interface{}, error) {
	if len(args) != 2 {
		return nil, fmt.Errorf("Atan2 function requires 2 arguments")
	}
	y, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("arguments must be float64")
	}
	x, ok := args[1].(float64)
	if !ok {
		return nil, fmt.Errorf("arguments must be float64")
	}
	return math.Atan2(y, x), nil
}

// Exp 返回 e 的 x 次幂的值
func Exp(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Exp function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Exp(x), nil
}

// Log 返回 x 的自然对数
func Log(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Log function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Log(x), nil
}

// Log10 返回 x 的以 10 为底的对数
func Log10(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Log10 function requires 1 argument")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("argument must be a float64")
	}
	return math.Log10(x), nil
}

// Mod 返回 x 除以 y 的余数
func Mod(args ...interface{}) (interface{}, error) {
	if len(args) != 2 {
		return nil, fmt.Errorf("Mod function requires 2 arguments")
	}
	x, ok := args[0].(float64)
	if !ok {
		return nil, fmt.Errorf("arguments must be float64")
	}
	y, ok := args[1].(float64)
	if !ok {
		return nil, fmt.Errorf("arguments must be float64")
	}
	return math.Mod(x, y), nil
}

// Inf 返回指定符号的正无穷大数值
func Inf(args ...interface{}) (interface{}, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("Inf function requires 1 argument")
	}
	sign, ok := args[0].(int)
	if !ok {
		return nil, fmt.Errorf("argument must be an int")
	}
	return math.Inf(sign), nil
}

govaluate应用场景

判断

动态条件判断

使用govaluate可以在运行时根据给定的条件字符串进行条件判断,例如,基于用户输入的条件判断是否执行特定的操作。

规则引擎

作为规则引擎的一部分,可以使用govaluate来解析和执行规则,例如,在金融领域中根据一系列条件制定交易策略。

配置文件解析

在解析配置文件时,可以使用govaluate来解析条件,以确定何时激活特定的配置选项。

求值

动态表达式求值

govaluate可以用于动态计算表达式的值,例如,在计算器应用中,可以让用户输入表达式,然后使用govaluate计算结果。

动态参数计算

当需要在运行时计算参数值时,可以使用govaluate,例如,在科学计算中,根据用户输入的参数计算函数的值。

动态数据过滤

在数据处理中,可以使用govaluate来动态过滤数据,例如,在数据分析应用中,根据用户输入的条件过滤数据。

以上是一些govaluate的应用场景,它的灵活性和易用性使其在各种领域都有广泛的应用。

相关推荐
杜杜的man2 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*2 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
半桶水专家2 小时前
go语言中package详解
开发语言·golang·xcode
llllinuuu2 小时前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s2 小时前
Golang--协程和管道
开发语言·后端·golang
王大锤43912 小时前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
产幻少年2 小时前
golang函数
golang
为什么这亚子2 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
半桶水专家2 小时前
用go实现创建WebSocket服务器
服务器·websocket·golang
材料苦逼不会梦到计算机白富美2 小时前
golang分布式缓存项目 Day 1
分布式·缓存·golang