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
}
相关推荐
fthux5 小时前
装闭 RenoPit 源码解析(09):AnalysisEngine装修闭坑分析主流程
人工智能·ai·开源·github·open source·renopit
JackieDYH5 小时前
Git 与 GitHub 新电脑配置指南(从零开始)
git·github·工具·使用教程
2603_965148115 小时前
如何解析JSON数据?API返回的商品信息处理教程
开发语言·数据库·python·自动化·json·api
知无不研8 小时前
lambda表达式的使用(3)
开发语言·c++·lambda
cfm_29148 小时前
SpringAI + Ollama 本地大模型
java·开发语言·人工智能·语言模型
C++ 老炮儿的技术栈10 小时前
基于Qt实现轻量化本地音乐播放器
开发语言·c++·qt·c·播放器·音乐
qq_4480111610 小时前
C语言中的柔性数组
c语言·开发语言·柔性数组
小白学大数据10 小时前
长周期爬虫的数据一致性:断点续爬 + 事务回滚保障采集质量
开发语言·爬虫·测试工具
zlinear数据采集卡10 小时前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
Poo_Chai10 小时前
QT emit信号后完整处理流程,包括槽函数响应流程
java·开发语言·数据库