【golang之路】——govaluate | 青训营笔记

617 阅读3分钟

引言

今天给大家介绍一个比较好玩的库,今天在看别人写的代码的时候发现在代码中用到了govaluate库,这个库可以让我们在golang代码中计算一个表达式的结果,这让我们在实现一些条件判断业务场景的时候非常便利。govaluate与 JavaScript 中的eval功能类似,用于计算任意表达式的值。

此类功能函数在 JavaScript/Python 等动态语言中比较常见。govaluate让 Go 这个编译型语言也有了这个能力!

快速使用

安装

$ go get github.com/Knetic/govaluate

使用

package main

import (
"fmt"
"github.com/Knetic/govaluate"
"log"
)

func main() {

    // 简单表达式 无参数
    expr, err := govaluate.NewEvaluableExpression("10>0")
    if err != nil {
    	log.Fatal("syntax error:",err)
    }
    result, err := expr.Evaluate(nil)
    if err != nil {
    	log.Fatal("evaluate error:err")
    }
    fmt.Println(result)
}

使用govaluate计算表达式只需要两步:

调用NewEvaluableExpression()将表达式转为一个表达式对象; 调用表达式对象的Evaluate方法,传入参数,返回表达式的值。 上面演示了一个很简单的例子,我们使用govaluate计算10 > 0的值,该表达式不需要参数,故传给Evaluate()方法nil值。当然,这个例子并不实用,显然我们直接在代码中计算10 > 0更简单。但问题是,有些时候我们并不知道需要计算的表达式的所有信息,甚至我们都不知道表达式的结构。这时govaluate的作用就体现出来了。

参数

govaluate支持在表达式中使用参数,调用表达式对象的Evaluate()方法时通过map[string]interface{}类型将参数传入计算。其中map的键为参数名,值为参数值。例如:

package main

import (
"fmt"
"github.com/Knetic/govaluate"
)

func main() {

    expr1, _ := govaluate.NewEvaluableExpression("foo >0")
    param:= make(map[string]interface{})
    param["foo"] = -1
    r1, _ := expr1.Evaluate(param)
    fmt.Printf("r1:%+v\n",r1)

    expr2, _ := govaluate.NewEvaluableExpression("a * b")
    param1 := make(map[string]interface{})
    param1["a"] = 2
    param1["b"] =4
    r2,_:= expr2.Evaluate(param1)
    fmt.Printf("r2:%+v",r2)

    expr3, _ := govaluate.NewEvaluableExpression("(a / b) * 100")
    param3 := make(map[string]interface{})
    param3["a"] = 1024
    param3["b"] = 512
    r3,_:= expr3.Evaluate(param3)
    fmt.Printf("r3:%+v",r3)

}

一次编译,多次运行 使用带参数的表达式,我们可以实现一个表达式的一次“编译”,多次运行。只需要使用编译返回的表达式对象即可,可多次调用其Evaluate()方法:

package main

import (
"fmt"
"github.com/Knetic/govaluate"
)

func main() {

    expr2, _ := govaluate.NewEvaluableExpression("a * b")
    param1 := make(map[string]interface{})
    param1["a"] = 2
    param1["b"] =4
    r2,_:= expr2.Evaluate(param1)
    fmt.Printf("r2:%+v",r2)
    param2 := make(map[string]interface{})
    param2["a"] = 5
    param2["b"] =6
    r23,_:= expr2.Evaluate(param2)
    fmt.Printf("r223:%+v",r23)

}

上面的代码的运行结果,第一次运行 根据传递的参数得到的结果是8,第二次运行,由于我们更换了参数,但是还是复用了【a*b】的表达式,所以结果是30。

函数 如果仅仅能进行常规的算数和逻辑运算,govaluate的功能会大打折扣。govaluate提供了自定义函数的功能。所有自定义函数需要先定义好,存入一个map[string]govaluate.ExpressionFunction变量中,然后调用govaluate.NewEvaluableExpressionWithFunctions()生成表达式,此表达式中就可以使用这些函数了。自定义函数类型为func (args ...interface{}) (interface{}, error),如果函数返回错误,则这个表达式求值返回错误。

总结

govaluate虽然支持的操作和类型有限,也能实现比较有意思的功能。例如,可以写一个 Web 服务,由用户自己编写表达式,设置参数,服务器算出结果。

参考

blog.csdn.net/hao134838/a…

darjun.github.io/2020/04/01/…