golang字节码编译脚本语言插件库tengo的使用

Golang字节码编译脚本语言插件库Tengo的使用

Tengo语言简介

Tengo是一种小型、动态、快速、安全的Go脚本语言。它之所以快速且安全,是因为它作为字节码在基于栈的虚拟机上编译/执行,该虚拟机是用原生Go编写的。

/* Tengo语言示例 */
fmt := import("fmt")

each := func(seq, fn) {
    for x in seq { fn(x) }
}

sum := func(init, seq) {
    each(seq, func(x) { init += x })
    return init
}

fmt.println(sum(0, [1, 2, 3]))   // "6"
fmt.println(sum("", [1, 2, 3]))  // "123"

主要特性

  • 简单且高度可读的语法
    • 带有类型强制的动态类型
    • 高阶函数和闭包
    • 不可变值
  • 安全嵌入和可扩展
  • 编译器/运行时使用原生Go编写(无外部依赖或cgo)
  • 可作为独立语言/REPL执行
  • 使用场景:规则引擎、状态机、数据管道、转译器

性能基准

语言/实现 fib(35) fibt(35) 类型
Tengo 2,315ms 3ms VM
go-lua 4,028ms 3ms VM
GopherLua 4,409ms 3ms VM
goja 5,194ms 4ms VM
starlark-go 6,954ms 3ms 解释器
gpython 11,324ms 4ms 解释器
Yaegi 11,715ms 10ms 解释器
otto 48,539ms 6ms 解释器
Anko 52,821ms 6ms 解释器
Go 47ms 2ms 原生
Lua 756ms 2ms 原生
Python 1,907ms 14ms 原生

快速开始

安装Tengo库:

go get github.com/d5/tengo/v2

基础使用示例

以下是一个简单的Go示例代码,演示如何编译/运行Tengo脚本代码并传递输入/输出值:

package main

import (
	"context"
	"fmt"

	"github.com/d5/tengo/v2"
)

func main() {
	// 创建新的Script实例
	script := tengo.NewScript([]byte(
`each := func(seq, fn) {
    for x in seq { fn(x) }
}

sum := 0
mul := 1
each([a, b, c, d], func(x) {
    sum += x
    mul *= x
})`))

	// 设置值
	_ = script.Add("a", 1)
	_ = script.Add("b", 9)
	_ = script.Add("c", 8)
	_ = script.Add("d", 4)

	// 运行脚本
	compiled, err := script.RunContext(context.Background())
	if err != nil {
		panic(err)
	}

	// 获取值
	sum := compiled.Get("sum")
	mul := compiled.Get("mul")
	fmt.Println(sum, mul) // "22 288"
}

简单表达式求值

如果你只需要计算一个简单的表达式,可以使用Eval函数:

res, err := tengo.Eval(ctx,
	`input ? "success" : "fail"`,
	map[string]interface{}{"input": 1})
if err != nil {
	panic(err)
}
fmt.Println(res) // "success"

参考资料

  • 语言语法
  • 对象类型
  • 运行时类型和运算符
  • 内置函数
  • 互操作性
  • Tengo CLI
  • 标准库
  • 语法高亮支持:VSCode、Atom、Vim

更多关于golang字节码编译脚本语言插件库tengo的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang字节码编译脚本语言插件库tengo的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Tengo: Golang 字节码编译脚本语言插件库

Tengo 是一个用 Go 编写的轻量级、可嵌入的脚本语言,它编译为字节码并在虚拟机上运行。Tengo 的设计目标是简单、高效且易于集成到 Go 应用程序中。

主要特性

  • 轻量级且快速
  • 动态类型
  • 类 C 语法
  • 可扩展性
  • 内存安全
  • 支持闭包
  • 编译为字节码

基本用法

安装

go get github.com/d5/tengo/v2

简单示例

package main

import (
	"fmt"
	"github.com/d5/tengo/v2"
)

func main() {
	// 创建脚本
	script := tengo.NewScript([]byte(`
		// Tengo 代码
		text := "Hello, Tengo!"
		number := 42
		result := text + " " + number
	`))

	// 运行脚本
	compiled, err := script.Run()
	if err != nil {
		panic(err)
	}

	// 获取结果
	result := compiled.Get("result")
	fmt.Println(result.String()) // 输出: Hello, Tengo! 42
}

高级功能

1. 调用 Go 函数

package main

import (
	"fmt"
	"github.com/d5/tengo/v2"
)

func main() {
	script := tengo.NewScript([]byte(`
		// 调用 Go 函数
		greet("Tengo")
	`))

	// 定义 Go 函数
	greet := tengo.UserFunction{
		Name: "greet",
		Value: func(args ...tengo.Object) (tengo.Object, error) {
			name := args[0].(*tengo.String).Value
			return &tengo.String{Value: fmt.Sprintf("Hello, %s!", name)}, nil
		},
	}

	// 添加函数到脚本
	_ = script.Add("greet", &greet)

	compiled, err := script.Run()
	if err != nil {
		panic(err)
	}

	fmt.Println(compiled.Get("greet").String())
}

2. 使用模块

package main

import (
	"fmt"
	"github.com/d5/tengo/v2"
	"github.com/d5/tengo/v2/stdlib"
)

func main() {
	script := tengo.NewScript([]byte(`
		math := import("math")
		sqrt := math.sqrt
		result := sqrt(16)
	`))

	// 添加标准库模块
	modules := stdlib.GetModuleMap("math")
	script.SetImports(modules)

	compiled, err := script.Run()
	if err != nil {
		panic(err)
	}

	fmt.Println(compiled.Get("result").String()) // 输出: 4
}

3. 错误处理

package main

import (
	"fmt"
	"github.com/d5/tengo/v2"
)

func main() {
	script := tengo.NewScript([]byte(`
		// 故意制造错误
		undefinedFunc()
	`))

	_, err := script.Run()
	if err != nil {
		// 获取运行时错误
		if runtimeErr, ok := err.(*tengo.RuntimeError); ok {
			fmt.Printf("Runtime error: %s at line %d\n", 
				runtimeErr.Message, 
				runtimeErr.Traceback[0].Line)
		} else {
			fmt.Printf("Compile error: %v\n", err)
		}
	}
}

性能优化技巧

  1. 复用脚本对象:对于频繁执行的脚本,可以预编译并复用
script := tengo.NewScript([]byte(`...`))
compiled, err := script.Compile()
if err != nil {
	panic(err)
}

// 多次执行
for i := 0; i < 100; i++ {
	_, err := compiled.Run()
	if err != nil {
		panic(err)
	}
}
  1. 限制执行时间:防止无限循环
script := tengo.NewScript([]byte(`while true {}`))
script.SetMaxAllocs(10000) // 限制分配次数

_, err := script.Run()
if err != nil {
	fmt.Println("Execution stopped:", err)
}

实际应用场景

  1. 配置解析:动态解析用户提供的配置
  2. 规则引擎:执行用户定义的业务规则
  3. 插件系统:允许用户扩展应用程序功能
  4. 模板引擎:动态生成内容
  5. 教育工具:教授编程概念

总结

Tengo 为 Go 应用程序提供了一个强大而灵活的脚本解决方案。它的轻量级设计和简单 API 使得集成变得非常容易,同时提供了足够的表达能力来处理复杂的脚本需求。无论是简单的表达式求值还是复杂的业务逻辑,Tengo 都能胜任。

更多高级功能和详细文档可以参考 Tengo 官方 GitHub 仓库

回到顶部