前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go: 如何高效的执行字符串算术表达式

go: 如何高效的执行字符串算术表达式

作者头像
超级大猪
发布2023-07-20 20:22:24
4310
发布2023-07-20 20:22:24
举报
文章被收录于专栏:大猪的笔记

数据系统常常需要在某个流节点执行简单的数据处理操作,例如单位的转换。

假设传入的值为input,在这一节点,输出的结果定义为 input * 8 / 1024, 为了方便运维同事修改,这个算式并未固化在代码中,而是使用string的方式定义在配置文件中。

如:

代码语言:javascript
复制
rules:
    rule1:  "input * 8 / 1024"

要在go中动态的载入string的算式并计算,一种简单的方式是使用语法解析树。生成这个算式对应的解析树,然后执行它。

代码语言:javascript
复制
import (
    "fmt"
    "go/parser"
    "go/token"
    "testing"
)
func TestMyAst(t *testing.T) {
    expression := "input*8/1024"

    // Create a file set for Go syntax tree
    fset := token.NewFileSet()

    // Parse the expression
    expr, err := parser.ParseExprFrom(fset, "", expression, 0)
    if err != nil {
        fmt.Printf("Failed to parse the expression: %v\n", err)
        return
    }

    // Create the context environment for evaluation
    data := 169661
    context := map[string]int64{
        "input": int64(data),
    }
    // Evaluate the expression
    result := eval(expr, context)
    logrus.Infof("result:%v %v", data, result)
}

此时,将传入参数放在context中,然后调用eval执行。

parser.ParseExprFrom的结果可以缓存下来,因为它只和算式有关。以提高性能。

eval的代码如下,通过完善eval,可以利用解析树执行更复杂的功能。下面的eval函数可以方便的执行二元运算,满足 input * 8 / 1024 的计算需求。

代码语言:javascript
复制
func eval(expr ast.Expr, context map[string]int64) int64 {
    switch e := expr.(type) {
    case *ast.Ident:
        // Handle identifiers (variables)
        value, ok := context[e.Name]
        if !ok {
            fmt.Printf("Undefined variable: %s\n", e.Name)
            return 0
        }
        return value
    case *ast.BasicLit:
        // Handle basic literals (constants)
        value, _ := strconv.ParseInt(e.Value, 0, 64)
        return value
    case *ast.BinaryExpr:
        // Handle binary expressions
        left := eval(e.X, context)
        right := eval(e.Y, context)
        switch e.Op {
        case token.ADD:
            return left + right
        case token.SUB:
            return left - right
        case token.MUL:
            return left * right
        case token.QUO:
            return left / right
        default:
            fmt.Printf("Unsupported operator: %s\n", e.Op)
            return 0
        }
    default:
        fmt.Printf("Unsupported expression type: %T\n", e)
        return 0
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-07-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档