前言:
在实际的业务开发而言,总会存在大大小小的规则判断,如判断某个用户年龄>12等,这时候,一般通用的写法都是采取动态表达式的方式,来方便规则本身的判断编写。
govaluate
与 JavaScript 中的eval
功能类似,用于计算任意表达式的值。此类功能函数在 JavaScript/Python 等动态语言中比较常见。govaluate
让 Go 这个编译型语言也有了这个能力!
下载方式:
go get github.com/Knetic/govaluate |
---|
官方说明:
提供支持评估任意C语言风格的算术/字符串表达式。 有时候,你无法提前知道表达式的具体形式,或者你希望这些表达式是可配置的。也许你的应用程序中有一组数据,你希望允许用户在将数据提交到数据库之前指定一些验证。或者你编写了一个监控框架,该框架能够收集大量指标,然后评估一些表达式以确定是否应对某些指标发出警报,但每个监控的警报条件都不同。 很多人最终会编写自己的一种不完整的评估语言,或者将表达式直接嵌入到可执行文件中,即使他们知道这些表达式可能会发生变化。这些策略可能有效,但它们需要时间来实现,用户需要时间来学习,并且随着需求的变化会引入技术债务。这个库旨在涵盖所有常见的 C 风格表达式,这样你就不必重新发明计算机上最古老的轮子之一。 |
---|
使用方法
(1)利用表达式直接执行:
package main
import (
"fmt"
"github.com/Knetic/govaluate"
)
func main() {
expression, err := govaluate.NewEvaluableExpression("10 > 0")
if err!=nil{
fmt.Println(err.Error())
return
}
result, err := expression.Evaluate(nil)
// result is now set to "true", the bool value.
if err!=nil{
fmt.Println(err.Error())
return
}
fmt.Println(result)
return
}
这里,是实则判断了"10 > 0"这一个表达式的执行值
(2)采取动态入参的方式执行:
package main
import (
"fmt"
"github.com/Knetic/govaluate"
)
func main() {
expression, err := govaluate.NewEvaluableExpression("foo > 0");
if err!=nil{
fmt.Println(err.Error())
return
}
parameters := make(map[string]interface{}, 8)
parameters["foo"] = -1;
result, err := expression.Evaluate(parameters);
if err!=nil{
fmt.Println(err.Error())
return
}
// result is now set to "false", the bool value.
fmt.Println(result)
return
}
这里,实则是将foo替换成了-1,去执行了“-1>0”这个表达式
(3)判断时间:
package main
import (
"fmt"
"github.com/Knetic/govaluate"
)
func main() {
expression, err := govaluate.NewEvaluableExpression("'2014-01-02' > '2014-01-01 23:59:59'")
if err != nil {
fmt.Println(err.Error())
return
}
result, err := expression.Evaluate(nil);
if err != nil {
fmt.Println(err.Error())
return
}
// result is now set to "false", the bool value.
fmt.Println(result)
return
}
支持的比对方式:
- 修饰符:+ - / * & | ^ ** % >> <<
- 比较运算符:> >= < <= == != =~ !~
- 逻辑运算符:|| &&
- 数值常量:64位浮点数(例如:12345.678)
- 字符串常量:单引号(例如:'foobar')
- 日期常量:单引号,使用任何 RFC3339、ISO8601、ruby 日期或 unix 日期的组合;日期解析会自动尝试任何字符串常量
- 布尔常量:true false
- 括号:用于控制运算顺序 ( )
- 数组:用逗号分隔的任何内容,括在括号内 (例如:(1, 2, 'foo'))
- 前缀:! - ~
- 三元条件运算符:? :
- 空合并运算符:??
一些特殊的使用方式:
(1)自定义函数:主要是用来一些自定义的计算
package main
import (
"fmt"
"github.com/Knetic/govaluate"
)
func main() { functions := map[string]govaluate.ExpressionFunction{
"strlen": func(args ...interface{}) (interface{}, error) {
length := len(args[0].(string))
return length, nil
},
}
exprString := "strlen('teststring')"
expr, _ := govaluate.NewEvaluableExpressionWithFunctions(exprString, functions)
result, _ := expr.Evaluate(nil)
// 这里会输出8
fmt.Println(result)
}
(2)访问器:主要是更自由的对结构体进行操作等等
package main
import (
"fmt"
"github.com/Knetic/govaluate"
)
type User struct {
FirstName string
LastName string
Age int
}
func (u User) Fullname() string {
return u.FirstName + " " + u.LastName
}
func main() {
u := User{FirstName: "huang", LastName: "zijian", Age: 18}
parameters := make(map[string]interface{})
parameters["u"] = u
expr, _ := govaluate.NewEvaluableExpression("u.Fullname()")
result, _ := expr.Evaluate(parameters)
fmt.Println("user", result)
expr, _ = govaluate.NewEvaluableExpression("u.Age > 18")
result, _ = expr.Evaluate(parameters)
fmt.Println("age > 18?", result)
}
总结:
govaluate 是一个很好的规则判断工具,你要不也来试试看?