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
}
相关推荐
阿珊和她的猫4 小时前
v-scale-scree: 根据屏幕尺寸缩放内容
开发语言·前端·javascript
fouryears_234176 小时前
Flutter InheritedWidget 详解:从生命周期到数据流动的完整解析
开发语言·flutter·客户端·dart
我好喜欢你~7 小时前
C#---StopWatch类
开发语言·c#
lifallen8 小时前
Java Stream sort算子实现:SortedOps
java·开发语言
IT毕设实战小研8 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
apocelipes9 小时前
下划线字段在golang结构体中的应用
golang
cui__OaO10 小时前
Linux软件编程--线程
linux·开发语言·线程·互斥锁·死锁·信号量·嵌入式学习
草梅友仁10 小时前
草梅 Auth 1.4.0 发布与 ESLint v9 更新 | 2025 年第 33 周草梅周报
vue.js·github·nuxt.js
鱼鱼说测试10 小时前
Jenkins+Python自动化持续集成详细教程
开发语言·servlet·php
艾莉丝努力练剑10 小时前
【洛谷刷题】用C语言和C++做一些入门题,练习洛谷IDE模式:分支机构(一)
c语言·开发语言·数据结构·c++·学习·算法