golang集成Duktape JavaScript引擎插件库go-duktape的使用

Golang集成Duktape JavaScript引擎插件库go-duktape的使用

Duktape是一个轻量级、可嵌入的JavaScript引擎。go-duktape是Duktape的Go语言绑定库,实现了大部分Duktape API。

安装

这个包完全支持go get,不需要安装任何外部C库。只需执行以下命令安装:

go get gopkg.in/olebedev/go-duktape.v3

基本使用示例

package main

import "fmt"
import "gopkg.in/olebedev/go-duktape.v3"

func main() {
  ctx := duktape.New()  // 创建新的Duktape上下文
  ctx.PevalString(`2 + 3`)  // 执行JavaScript表达式
  result := ctx.GetNumber(-1)  // 从栈顶获取结果
  ctx.Pop()  // 弹出栈顶元素
  fmt.Println("result is:", result)
  // 为防止内存泄漏,使用完上下文后记得销毁
  ctx.DestroyHeap()
}

Go函数绑定

可以将Go函数绑定到JavaScript上下文中:

package main

import "fmt"
import "gopkg.in/olebedev/go-duktape.v3"

func main() {
  ctx := duktape.New()
  // 将Go函数绑定为JavaScript全局函数log
  ctx.PushGlobalGoFunction("log", func(c *duktape.Context) int {
    fmt.Println(c.SafeToString(-1))  // 打印传入的参数
    return 0
  })
  ctx.PevalString(`log('Go lang Go!')`)  // 调用绑定的函数
}

运行结果:

$ go run *.go
Go lang Go!

定时器功能

可以注入定时器函数到全局作用域:

package main

import "fmt"
import "gopkg.in/olebedev/go-duktape.v3"

func main() {
  ctx := duktape.New()

  // 注入setTimeout、setInterval、clearTimeout、clearInterval到全局作用域
  ctx.PushTimers()

  ch := make(chan string)
  ctx.PushGlobalGoFunction("second", func(_ *Context) int {
    ch <- "second step"
    return 0
  })
  ctx.PevalString(`
    setTimeout(second, 0);  // 异步调用
    print('first step');    // 同步调用
  `)
  fmt.Println(<-ch)
}

运行结果:

$ go run *.go
first step
second step

命令行工具

安装命令行工具:

go get gopkg.in/olebedev/go-duktape.v3/...

执行JavaScript文件:

$GOPATH/bin/go-duk file.js

性能对比

引擎 执行时间
otto 200.13s
anko 231.19s
agora 149.33s
GopherLua 8.39s
go-duktape 9.80s

注意事项

  1. 该包尚未完全测试,使用时需谨慎
  2. 使用完上下文后务必调用DestroyHeap()防止内存泄漏
  3. Go和JavaScript上下文之间的绑定功能尚未完全实现

贡献

欢迎提交Pull Request!讨论问题时请提交包含提案和更改的Pull Request。


更多关于golang集成Duktape JavaScript引擎插件库go-duktape的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang集成Duktape JavaScript引擎插件库go-duktape的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用go-duktape在Golang中集成Duktape JavaScript引擎

Duktape是一个轻量级、可嵌入的JavaScript引擎,而go-duktape是它的Golang绑定。下面我将介绍如何在Golang项目中使用go-duktape来执行JavaScript代码。

安装go-duktape

首先需要安装go-duktape库:

go get github.com/olebedev/go-duktape

基本使用示例

package main

import (
	"fmt"
	"github.com/olebedev/go-duktape"
)

func main() {
	// 创建新的Duktape上下文
	ctx := duktape.New()
	
	// 执行简单的JavaScript代码
	err := ctx.PevalString(`var x = 10; var y = 20; x + y;`)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	
	// 从栈顶获取结果
	result := ctx.GetNumber(-1)
	fmt.Println("Result:", result) // 输出: Result: 30
	
	// 弹出结果
	ctx.Pop()
	
	// 定义一个Go函数供JavaScript调用
	ctx.PushGlobalGoFunction("add", func(c *duktape.Context) int {
		a := c.GetNumber(0) // 获取第一个参数
		b := c.GetNumber(1) // 获取第二个参数
		c.PushNumber(a + b) // 将结果压入栈
		return 1            // 返回结果数量
	})
	
	// 调用我们定义的函数
	ctx.PevalString(`print("10 + 20 =", add(10, 20));`)
	
	// 销毁上下文
	ctx.Destroy()
}

高级功能示例

1. 在Go和JavaScript之间传递复杂数据

func jsonExample() {
	ctx := duktape.New()
	defer ctx.Destroy()
	
	// 定义一个JSON字符串
	jsonStr := `{"name": "Alice", "age": 25, "hobbies": ["reading", "swimming"]}`
	
	// 在JavaScript中解析JSON
	ctx.PevalString(fmt.Sprintf(`var person = %s;`, jsonStr))
	
	// 从JavaScript中获取属性
	ctx.PevalString(`JSON.stringify(person)`)
	fmt.Println("Person as JSON:", ctx.GetString(-1))
	ctx.Pop()
	
	// 或者直接操作对象
	ctx.GetGlobalString("person")
	ctx.GetPropString(-1, "name")
	fmt.Println("Name:", ctx.GetString(-1))
	ctx.Pop2()
}

2. 错误处理

func errorHandling() {
	ctx := duktape.New()
	defer ctx.Destroy()
	
	// 故意执行有错误的代码
	err := ctx.PevalString(`function foo() { bar(); } foo();`)
	if err != nil {
		// 获取错误堆栈
		ctx.GetPropString(-1, "stack")
		fmt.Println("Error:", ctx.GetString(-1))
		ctx.Pop()
	}
}

3. 异步执行JavaScript

func asyncExample() {
	ctx := duktape.New()
	defer ctx.Destroy()
	
	// 注册setTimeout模拟函数
	ctx.PushGlobalGoFunction("setTimeout", func(c *duktape.Context) int {
		// 获取回调和延迟时间
		delay := c.GetNumber(1)
		// 这里只是模拟,实际应该使用goroutine实现真正的异步
		fmt.Printf("Will execute after %.0fms\n", delay)
		return 0
	})
	
	ctx.PevalString(`
		setTimeout(function() {
			print('This executes later');
		}, 1000);
		print('This executes first');
	`)
}

性能考虑

  1. Duktape是一个轻量级引擎,适合嵌入式使用,但不适合高性能场景
  2. 频繁的Go-JavaScript互操作会有性能开销
  3. 对于复杂应用,考虑将逻辑尽量放在一边(全Go或全JavaScript)

实际应用场景

  1. 配置文件使用JavaScript编写
  2. 实现业务规则引擎
  3. 提供用户脚本扩展功能
  4. 在Go应用中嵌入JavaScript解释器

总结

go-duktape为Golang提供了简单有效的JavaScript执行能力,适合需要轻量级脚本支持的场景。通过上面的示例,你可以快速上手集成JavaScript功能到你的Go应用中。

回到顶部