该库允许程序评估任意算术/字符串/逻辑表达式。 支持访问变量和调用自定义函数。
该项目被认为是稳定的,并已在生产系统中使用。 请使用问题跟踪器提出任何问题、反馈和错误报告。
本项目根据MIT许可证的条款进行许可。
在示例文件夹中可以找到一个评估表达式的小型CLI演示:
go get -u github.com/maja42/goval
cd $GOPATH/src/github.com/maja42/goval/
go run example/main.go
最小示例:
eval := goval.NewEvaluator() result, err := eval.Evaluate(`42 > 21`, nil, nil) // 返回 <true, nil>
访问变量:
eval := goval.NewEvaluator() variables := map[string]interface{}{ "uploaded": 146, "total": 400, } result, err := eval.Evaluate(`uploaded * 100 / total`, variables, nil) // 返回 <36, nil>
调用函数:
// 实现 strlen() eval := goval.NewEvaluator() variables := map[string]interface{}{ "os": runtime.GOOS, "arch": runtime.GOARCH, } functions := make(map[string]goval.ExpressionFunction) functions["strlen"] = func(args ...interface{}) (interface{}, error) { str := args[0].(string) return len(str), nil } result, err := eval.Evaluate(`strlen(arch[:2]) + strlen("text")`, variables, functions) // 返回 <6, nil>
自定义函数允许扩展任意功能,如正则表达式匹配:
// 实现正则表达式(省略错误处理) functions := make(map[string]goval.ExpressionFunction) functions["matches"] = func(args ...interface{}) (interface{}, error) { str := args[0].(string) exp := args[1].(string) reg := regexp.MustCompile(exp) return reg.MatchString(str), nil } eval.Evaluate(`matches("text", "[a-z]+")`, nil, functions) // 返回 <true, nil> eval.Evaluate(`matches("1234", "[a-z]+")`, nil, functions) // 返回 <false, nil>
该库完全支持以下类型:nil
、bool
、int
、float64
、string
、[]interface{}
(=数组) 和 map[string]interface{}
(=对象)。
在表达式中,int
和 float64
都具有 number
类型,并且完全透明。
如果需要,数值将在 int
和 float64
之间自动转换,只要不损失精度。
数组和对象是无类型的。它们可以存储任何其他值("混合数组")。
不支持结构体,以保持功能清晰和可管理。 它们会引入太多边缘情况和未解决的问题,因此不在范围内。
可以直接访问自定义变量。 变量是只读的,不能在表达式内修改。
示例:
var
var.field
var[0]
var["field"]
var[anotherVar]
var["fie" + "ld"].field[42 - var2][0]
可以在表达式中调用自定义函数。
示例:
rand()
floor(42)
min(4, 3, 12, max(1, 3, 3))
len("te" + "xt")
可以在表达式中定义任何字面量。
字符串字面量可以用双引号 "
或反引号 括起来。 十六进制字面量以
0x` 前缀开始。
示例:
nil
true
false
3
3.2
"Hello, 世界!\n"
"te\"xt"
`te"xt`
[0, 1, 2]
[]
[0, ["text", false], 4.2]
{}
{"a": 1, "b": {c: 3}}
{"key" + 42: "value"}
{"k" + "e" + "y": "value"}
0xA // 10
0x0A // 10
0xFF // 255
0xFFFFFFFF // 32位应用:-1 64位应用:4294967295
0xFFFFFFFFFFFFFFFF // 64位应用:-1 32位应用:错误
可以访问数组和对象字面量的元素:
示例:
[1, 2, 3][1] // 2
[1, [2, 3, 42][1][2] // 42
{"a": 1}.a // 1
{"a": {"b": 42}}.a.b // 42
{"a": {"b": 42}}["a"]["b"] // 42
运算符优先级严格遵循 C/C++ 规则。
括号 ()
用于控制优先级。
示例:
1 + 2 * 3 // 7
(1 + 2) * 3 // 9
+
-
*
/
如果两边都是整数,结果值也是整数。 否则,结果将是浮点数。
示例:
3 + 4 // 7
2 + 2 * 3 // 8
2 * 3 + 2.5 // 8.5
12 - 7 - 5 // 0
24 / 10 // 2
24.0 / 10 // 2.4
**
如果两边都是整数,并且结果可以表示为整数,则结果值也是整数。 否则,结果将是浮点数。
示例:
2 ** 4 // 16
10 ** 3 // 1000
10 ** -6 // 0.000001
2.5 ** -2.5 // 0.10119...
%
如果两边都是整数,结果值也是整数。 否则,结果将是浮点数。
示例:
4 % 3 // 1
144 % 85 // -55
5.5 % 2 // 1.5
10 % 3.5 // 3.0
-
(一元减号)对右侧的数字取反。
示例:
-4 // -4
5 + -4 // 1
-5 - -4 // -1
1 + --1 // 语法错误
-(4+3) // -7
-varName
+
如果 +
运算符的左侧或右侧是 string
,则执行字符串连接。
支持字符串、数字、布尔值和 nil。
示例:
"text" + 42 // "text42"
"text" + 4.2 // "text4.2"
42 + "text" // "42text"
"text" + nil // "textnil"
"text" + true // "texttrue"
+
如果 +
运算符的两侧都是数组,它们将被连接
示例:
[0, 1] + [2, 3] // [0, 1, 2, 3]
[0] + [1] + [[2]] + [] // [0, 1, [2]]
+
如果 +
运算符的两侧都是对象,它们的字段将被合并到一个新对象中。
如果两个对象包含相同的键,右侧对象的值将覆盖左侧对象的值。
示例:
{"a": 1} + {"b": 2} + {"c": 3} // {"a": 1, "b": 2, "c": 3}
{"a": 1, "b": 2} + {"b": 3, "c": 4} // {"a": 1, "b": 3, "c": 4}
{"b": 3, "c": 4} + {"a": 1, "b": 2} // {"a": 1, "b": 2, "c": 4}
==
,不等于 !=
对两个操作数执行深度比较。
在比较 int
和 float64
时,
整数将被转换为浮点数。
<
、>
、<=
、>=
比较两个数字。如果运算符的一侧是整数,另一侧是浮点数, 整数将被转换。这可能会导致非常大的数字在转换过程中被舍入,从而产生意外结果。
示例:
3 <-4 // false
45 > 3.4 // false
-4 <= -1 // true
3.5 >= 3.5 // true
&&
,或 ||
示例:
true && true // true
false || false // false
true || false && false // true
false && false || true // true
!
对右侧的布尔值取反。
示例:
!true // false
!false // true
!!true // true
!varName
? :
如果表达式解析为 true
,运算符解析为左操作数。
如果表达式解析为 false
,运算符解析为右操作数。
示例:
true ? 1 : 2 // 1
false ? 1 : 2 // 2
2 < 5 ? "a" : 1.5 // "a"
9 > 12 ? "a" : [42] // [42]
false ? (true ? 1:2) : (true ? 3:4) // 3
请注意,所有操作数都会被解析(没有短路)。
在以下示例中,两个函数都会被调用(func2
的返回值简单地被忽略):
true ? func1() : func2()
|
,逻辑与 &
,逻辑异或 ^
如果运算符的一侧是浮点数,则如果可能会将该数字转换为整数。 如果在该过程中会丢失小数位,则认为是类型错误。 结果数字始终是整数。
示例:
8 | 2 // 10
9 | 5 // 13
8 | 2.0 // 10
8 | 2.1 // 类型错误
13 & 10 // 8
10 & 15.0 & 2 // 2
13 ^ 10 // 7
10 ^ 15 ^ 1 // 4
~
如果对浮点数执行,则如果可能会将该数字转换为整数。 如果在该过程中会丢失小数位,则认为是类型错误。 结果数字始终是整数。
结果可能因32位和64位架构而异。
示例:
~-1 // 0
(~0xA55A) & 0xFFFF // 0x5AA5
(~0x5AA5) & 0xFFFF // 0xA55A
~0xFFFFFFFF // 64位应用: 0xFFFFFFFF 00000000; 32位应用: 0x00
~0xFFFFFFFF FFFFFFFF // 64位应用: 0x00; 32位: 错误
<<
, >>
如果运算符的一侧是浮点数,则如果可能会将该数字转换为整数。 如果在该过程中会丢失小数位,则认为是类型错误。 结果数字始终是整数。
右移时执行符号扩展。 结果可能因32位和64位架构而异。
示例:
1 << 0 // 1
1 << 1 // 2
1 << 2 // 4
8 << -1 // 4
8 >> -1 // 16
1 << 31 // 0x00000000 80000000 64位应用: 2147483648; 32位应用: -2147483648
1 << 32 // 0x00000001 00000000 32位应用: 0 (溢出)
1 << 63 // 0x80000000 00000000 32位应用: 0 (溢出); 64位应用: -9223372036854775808
1 << 64 // 0x00000000 00000000 0 (溢出)
0x80000000 00000000 >> 63 // 0xFFFFFFFF FFFFFFFF 64位: -1 (符号扩展); 32位: 错误 (无法解析数字字面量)
0x80000000 >> 31 // 64位: 0x00000000 0000001; 32位: 0xFFFFFFFF (-1, 符号扩展)
in
返回数组是否包含特定元素的布尔值。
示例:
"txt" in [nil, "hello", "txt", 42] // true
true in [nil, "hello", "txt", 42] // false
nil in [nil, "hello", "txt", 42] // true
42.0 in [nil, "hello", "txt", 42] // true
2 in [1, [2, 3], 4] // false
[2, 3] in [1, [2, 3], 4] // true
[2, 3, 4] in [1, [2, 3], 4] // false
[a:b]
切片字符串并返回给定的子字符串。 字符串按字节索引。多字节字符需要小心处理。
开始索引表示子字符串中存在的第一个字节。
结束索引表示子字符串中不存在的最后一个字节。
因此,有效索引范围为 [0, len(str)]
。
示例:
"abcdefg"[:] // "abcdefg"
"abcdefg"[1:] // "bcdefg"
"abcdefg"[:6] // "abcdef"
"abcdefg"[2:5] // "cde"
"abcdefg"[3:4] // "d"
// 字符 世 和 界 都需要3个字节:
"Hello, 世界"[7:13] // "世界"
"Hello, 世界"[7:10] // "世"
"Hello, 世界"[10:13] // "界"
[a:b]
切片数组并返回给定的子数组。
开始索引表示子数组中存在的第一个元素。
结束索引表示子数组中不存在的最后一个元素。
因此,有效索引范围为 [0, len(arr)]
。
示例:
// 假设 `arr := [0, 1, 2, 3, 4, 5, 6]`:
arr[:] // [0, 1, 2, 3, 4, 5, 6]
arr[1:] // [1, 2, 3, 4, 5, 6]
arr[:6] // [0, 1, 2, 3, 4, 5]
arr[2:5] // [2, 3, 4]
arr[3:4] // [3]
如果你正在寻找通用评估库, 你也可以看看 Knetic/govaluate。 我自己使用过该库,但由于存在几个缺点,我决定创建 goval。 主要区别是:
int
和 float64
之间不透明的区分。int
类型的数字)。.
和 []
语法访问变量(映射)[]
的数组字面量以及带有 {}
的对象字面量int
的大小而表现不同。一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
字节跳动发布的AI编程神器IDE
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。
OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。
openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优 势。
高分辨率纹理 3D 资产生成
Hunyuan3D-2 是腾讯开发的用于 3D 资产生成的强大工具,支持从文本描述、单张图片或多视角图片生成 3D 模型,具备快速形状生成能力,可生成带纹理的高质量 3D 模型,适用于多个领域,为 3D 创作提供了高效解决方案。
一个具备存储、管理和客户端操作等多种功能的分布式文件系统相关项目。
3FS 是一个功能强大的分布式文件系统项目,涵盖了存储引擎、元数据管理、客户端工具等多个模块。它支持多种文件操作,如创建文件和目录、设置布局等,同时具备高效的事件循环、节点选择和协程池管理等特性。适用于需要大规模数据存储和管理的场景,能够提高系统的性能和可靠性,是分布式存储领域的优质解决方案。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号