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
}
相关推荐
SeaTunnel4 小时前
从 Python Script 地狱到标准化数据集成框架
大数据·开发语言·python·程序员·代码·seatunnel
碎光拾影4 小时前
ARM交叉工具链各工具作用及IMX6ULL平台LED+蜂鸣器裸机程序实现
java·开发语言·数据库
CCPC不拿奖不改名4 小时前
大模型推理架构与开源生态知识整理
数据库·windows·python·架构·langchain·开源·github
Marst Code4 小时前
(python)2026Plotly 库评估:交互式可视化到底值不值得引入?
开发语言·python
Miao121315 小时前
微服务 API 测试实践:海外某民宿平台如何构建模式驱动测试基础设施
java·开发语言
William.csj5 小时前
BaiduPCS-Go——下载百度网盘文件的工具
golang·baidupc
CRMEB系统商城6 小时前
开源自建还是SaaS订阅?算一笔3年经济账
java·大数据·开发语言·开源
keyipatience7 小时前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
我的xiaodoujiao7 小时前
快速学习Python基础知识详细图文教程9--函数进阶
开发语言·python·学习·测试工具
爱喝水的鱼丶8 小时前
SAP-ABAP:ALV通用封装实践——搭建可复用的ALV开发工具类,减少80%重复代码
开发语言·性能优化·sap·abap·erp·alv