代码已开源:github.com/StrangeYear…
goeval是一个使用YACC和Ragel,基于状态机模式构建的GO语言表达式计算引擎,可适用于一些动态条件判断场景。
对于相同表达式进行多次判断的场景,这个库可能不适合。因为每次解析都会进行判定,没有缓存表达式。对于动态表达式判断场景,性能优于其他开源的go表达式引擎库。
支持的运算
- 修饰符: +、-、/、*、%
- 比较器: >、>=、<、<=、==、!=、=~、!~、in
- 逻辑运算: ||、&&
- 数字常量: 12345.678、123(转为float64)
- 字符串常量: "foo"、'bar'、`baz`(支持转义"、'、`)
- 布尔常量: true、false
- 括号控制求值顺序: ( )
- 数组常量或嵌套变量: [1, 2, 'foo', bar](bar为变量)
- 前缀: ! - ~
- 三元表达式: 5 > 1 ? 4 : 3 (返回值4)
- 空值默认值: foo ?? 'bar' (当foo变量为空时,会使用'bar'作为返回值)
使用方式
- 基础表达式:
10 > 0 - 参数表达式:
foo > 0 - 特殊参数表达式(包含空格及比较符号等):
$.["foo bar"] > 0、$.["response-time"] > 0 - 嵌套参数表达式:
foo.bar > 0、foo.bar[0] > 0、foo["bar"] > 0、$.["foo bar"].$.["foo baz"] > 0 - GJSON表达式:
$["response-time"] > 0、$["data.items.0"] < 0(gjson) - 带参数的算术表达式:
(requests_made * requests_succeeded / 100) >= 90 - 字符串比较:
http_response_body == "service is ok" - 日期比较表达式:
now() > date(“2022-05-01 23:59:59”) - 时间戳比较表达式:
date(1651467728) > date("2022-05-01 23:59:59") - 字符长度计算表达式:
strlen("someReallyLongInputString") <= 16
自定义方法
示例:计算最大值
func TestFunc(t *testing.T) {
val, err := Full(
WithFunc("max", func(args ...interface{}) (interface{}, error) {
if len(args) == 0 {
return 0, nil
}
max := func(a, b float64) float64 {
if a > b {
return a
}
return b
}
var val float64
val, ok := args[0].(float64)
if !ok {
return 0, fmt.Errorf("max() expects number arguments")
}
for i, arg := range args {
if i == 0 {
continue
}
arg, ok := arg.(float64)
if !ok {
return 0, fmt.Errorf("max() expects number arguments")
}
val = max(val, arg)
}
return val, nil
}),
).EvalFloat(`max(1,2,3,a)`, map[string]interface{}{"a": float64(6)})
if err != nil {
t.Fatalf("Eval() error = %v", err)
}
t.Log(val == 6)
// output: true
}
性能测试
goos: darwin
goarch: amd64
pkg: github.com/StrangeYear/goeval
cpu: Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
BenchmarkEvaluationSingle-16 2371440 508.2 ns/op
BenchmarkEvaluationNumericLiteral-16 979606 1178 ns/op
BenchmarkEvaluationLiteralModifiers-16 604010 1903 ns/op
BenchmarkEvaluationParameter-16 1344694 885.3 ns/op
BenchmarkEvaluationParameters-16 712880 1594 ns/op
BenchmarkEvaluationParametersModifiers-16 478978 2434 ns/op
BenchmarkComplexExpression-16 143646 8187 ns/op
BenchmarkRegexExpression-16 451497 2595 ns/op
BenchmarkFunc-16 268068 4476 ns/op
BenchmarkJSON-16 460448 2557 ns/op
BenchmarkNested-16 520017 2287 ns/op
BenchmarkSpecial-16 1323009 908.7 ns/op
PASS