go的工具库:github.com/expr-lang/expr

github.com/expr-lang/expr 是一个 Go 语言的表达式求值库,它允许你在运行时安全地执行表达式。主要用途包括:

1.表达式求值:

go 复制代码
program, err := expr.Compile("2 + 2")
if err != nil {
    // 处理错误
}
result, err := expr.Run(program, nil)
// result 将是 4

2.条件表达式

go 复制代码
program, err := expr.Compile("age > 18 && name == 'John'")
if err != nil {
    // 处理错误
}
result, err := expr.Run(program, map[string]interface{}{
    "age": 20,
    "name": "John",
})
// result 将是 true

3.复杂表达式

go 复制代码
program, err := expr.Compile("sum(numbers) > 100 && len(numbers) > 0")
if err != nil {
    // 处理错误
}
result, err := expr.Run(program, map[string]interface{}{
    "numbers": []int{1, 2, 3, 4, 5},
    "sum": func(numbers []int) int {
        sum := 0
        for _, n := range numbers {
            sum += n
        }
        return sum
    },
})

主要特点:

安全性:表达式在沙箱环境中执行

性能:编译后的表达式执行速度快

灵活性:支持自定义函数和变量

类型安全:支持类型检查

常见用途:

规则引擎

配置验证

动态条件判断

数据过滤

业务规则执行

例如,在配置验证中:

go 复制代码
type Config struct {
    MaxSize int
    MinSize int
}

config := Config{MaxSize: 100, MinSize: 10}
program, err := expr.Compile("MaxSize > MinSize")
if err != nil {
    // 处理错误
}
result, err := expr.Run(program, config)
if err != nil {
    // 处理错误
}
if !result.(bool) {
    // 配置无效
}

在业务规则中:

go 复制代码
type Order struct {
    Amount float64
    Items  int
}

order := Order{Amount: 100, Items: 5}
program, err := expr.Compile("Amount > 50 && Items > 0")
if err != nil {
    // 处理错误
}
result, err := expr.Run(program, order)
if err != nil {
    // 处理错误
}
if result.(bool) {
    // 订单有效
}

使用注意事项

expr.Compile 方法的性能和使用注意事项如下:

1.编译性能:

go 复制代码
// 编译性能
program, err := expr.Compile("2 + 2")

编译时间通常很短,在微秒级别

但对于复杂表达式,编译时间会相应增加

建议缓存编译结果,避免重复编译

2.缓存编译结果:

go 复制代码
// 使用 sync.Map 缓存编译结果
var compiledExpressions sync.Map

func getCompiledExpression(expr string) (*expr.Program, error) {
    // 先查找缓存
    if cached, ok := compiledExpressions.Load(expr); ok {
        return cached.(*expr.Program), nil
    }
    
    // 编译新表达式
    program, err := expr.Compile(expr)
    if err != nil {
        return nil, err
    }
    
    // 存入缓存
    compiledExpressions.Store(expr, program)
    return program, nil
}

3.错误处理:

go 复制代码
// 完整的错误处理
program, err := expr.Compile("invalid expression")
if err != nil {
    switch e := err.(type) {
    case *expr.Error:
        // 处理表达式错误
        log.Printf("Expression error: %v", e)
    default:
        // 处理其他错误
        log.Printf("Unexpected error: %v", e)
    }
    return
}

4.类型安全:

go 复制代码
// 使用类型检查
env := map[string]interface{}{
    "age": 20,
    "name": "John",
}

// 编译时进行类型检查
program, err := expr.Compile("age > 18 && name == 'John'", expr.Env(env))
if err != nil {
    // 处理类型错误
    return
}

5.并发安全:

go 复制代码
// 使用互斥锁保护缓存
var (
    cache     = make(map[string]*expr.Program)
    cacheLock sync.RWMutex
)

func getCompiledExpression(expr string) (*expr.Program, error) {
    cacheLock.RLock()
    if program, ok := cache[expr]; ok {
        cacheLock.RUnlock()
        return program, nil
    }
    cacheLock.RUnlock()

    cacheLock.Lock()
    defer cacheLock.Unlock()
    
    program, err := expr.Compile(expr)
    if err != nil {
        return nil, err
    }
    
    cache[expr] = program
    return program, nil
}
相关推荐
Wenweno0o17 小时前
0基础Go语言Eino框架智能体实战-chatModel
开发语言·后端·golang
逛逛GitHub17 小时前
面壁智能开源了支持音色设计、克隆、30语言+9 种方言的语音大模型
github
chenjingming66617 小时前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter
小领航18 小时前
用 Three.js + Vue 3 打造炫酷的 3D 行政地图可视化组件
前端·github
李同学Lino18 小时前
别再让Agent瞎写屎山代码了!带你用Superpowers重塑Vibe Coding体验(附保姆级教程)
github
cch891818 小时前
Python主流框架全解析
开发语言·python
不爱吃炸鸡柳18 小时前
C++ STL list 超详细解析:从接口使用到模拟实现
开发语言·c++·list
十五年专注C++开发18 小时前
RTTR: 一款MIT 协议开源的 C++ 运行时反射库
开发语言·c++·反射
Momentary_SixthSense18 小时前
设计模式之工厂模式
java·开发语言·设计模式
‎ദ്ദിᵔ.˛.ᵔ₎18 小时前
STL 栈 队列
开发语言·c++