在 golang 中执行 javascript 代码的方案详解

简介: 本文介绍了在 Golang 中执行 JavaScript 代码的四种方法:使用 `otto` 和 `goja` 嵌入式 JavaScript 引擎、通过 `os/exec` 调用 Node.js 外部进程以及使用 WebView 嵌入浏览器。每种方法都有其适用场景,如嵌入简单脚本、运行复杂 Node.js 脚本或在桌面应用中显示 Web 内容。

在 Golang 中执行 JavaScript 代码可以通过几种不同的方式来实现。通常,这些方法包括使用外部 JavaScript 引擎或通过调用 JavaScript 引擎的绑定库。下面是一些常用的方法:

1. 使用 otto 库(嵌入式 JavaScript 引擎)

otto 是一个纯 Go 语言编写的 JavaScript 解释器,允许在 Go 程序中直接运行 JavaScript 代码,而不需要启动外部进程。

安装 otto

go get github.com/robertkrimen/otto

示例代码:

package main

import (
    "fmt"
    "github.com/robertkrimen/otto"
)

func main() {
   
    // 创建 JavaScript 解释器
    vm := otto.New()

    // 执行 JavaScript 代码
    _, err := vm.Run(`
        function greet() {
            return "Hello from JavaScript!";
        }
        greet();
    `)

    if err != nil {
   
        fmt.Println("Error:", err)
        return
    }

    // 获取 JavaScript 函数的返回值
    result, err := vm.Call("greet", nil)
    if err != nil {
   
        fmt.Println("Error calling function:", err)
        return
    }

    // 输出结果
    fmt.Println(result.String()) // 输出:Hello from JavaScript!
}

说明:

  • otto.New() 创建一个新的 JavaScript 解释器。
  • vm.Run() 用于运行 JavaScript 代码。
  • vm.Call() 用于调用已定义的 JavaScript 函数。

otto 适用于在 Go 中嵌入 JavaScript 的场景,但它的性能和支持的功能相对有限。它适合用于执行简单的 JavaScript 代码,但不适合高性能要求的复杂应用。

2. 使用 goja 库(嵌入式 JavaScript 引擎)

goja 是另一个 Go 语言实现的 JavaScript 引擎,支持 ES5 和部分 ES6 特性,适合在 Go 中嵌入 JavaScript。

安装 goja

go get github.com/dop251/goja

示例代码:

package main

import (
    "encoding/json"
    "fmt"

    "github.com/dop251/goja"
)

func main() {
   
    // 创建 JavaScript 运行时
    vm := goja.New()

    // 执行 JavaScript 代码:定义一个函数
    res, err := vm.RunString(`
        function greet(name) {
            return "Hello, " + name + "!";
        }
        greet("rico");
    `)
    if err != nil {
   
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(res)

    // 获取 JavaScript 中定义的 greet 函数
    // greetFunc := vm.Get("greet")
    // if greetFunc == nil {
   
    //     fmt.Println("Error: greet function not found")
    //     return
    // }

    // 调用 JavaScript 中的 greet 函数
    result, err := vm.RunString(`greet("Alice");`)
    if err != nil {
   
        fmt.Println("Error calling greet:", err)
        return
    }

    // 转换返回的值为 Go 字符串
    //resultValue := result.Export()

    // 输出结果
    jstr, err := json.Marshal(result)
    if err != nil {
   
        fmt.Println("Error with json.Marshal() :", err)
        return
    }
    fmt.Println("result 1: " + string(jstr)) // 输出:Hello, Alice!

    // 执行另一段 JavaScript 代码:定义 farewell 函数
    _, err = vm.RunString(`
        function farewell(name) {
            return "Goodbye, " + name + "!";
        }
    `)
    if err != nil {
   
        fmt.Println("Error:", err)
        return
    }

    // 获取 farewell 函数
    farewellFunc := vm.Get("farewell")
    if farewellFunc == nil {
   
        fmt.Println("Error: farewell function not found")
        return
    }

    // 调用 farewell 函数
    result2, err := vm.New(farewellFunc, vm.ToValue("Bob"))
    if err != nil {
   
        fmt.Println("Error calling farewell:", err)
        return
    }

    // 转换返回的值为 Go 字符串
    resultStr2 := result2.Export()

    // 输出结果
    fmt.Println(resultStr2) // 输出:Goodbye, Bob!
}

说明:

  • goja.New() 创建一个新的 JavaScript 运行时。
  • vm.RunString() 用于执行 JavaScript 代码。
  • vm.Get() 用于获取 JavaScript 环境中的值。

goja 库支持较多的现代 JavaScript 特性,相比于 otto,它在性能和功能上更强大。

3. 使用 Node.js 通过 os/exec 执行外部进程

如果你希望在 Golang 中执行更复杂的 JavaScript 代码,或者需要运行 Node.js 中的脚本,可以使用 os/exec 启动 Node.js 进程执行 JavaScript 脚本。

示例代码:

package main

import (
    "fmt"
    "log"
    "os/exec"
)

func main() {
   
    // 定义要执行的 JavaScript 代码
    jsCode := `
        console.log("Hello from Node.js!");
    `

    // 执行 Node.js 进程
    cmd := exec.Command("node", "-e", jsCode)
    output, err := cmd.CombinedOutput()

    if err != nil {
   
        log.Fatal(err)
    }

    // 输出 Node.js 进程的执行结果
    fmt.Println(string(output))
}

说明:

  • exec.Command("node", "-e", jsCode) 启动 Node.js 并通过 -e 选项执行内联的 JavaScript 代码。
  • cmd.CombinedOutput() 执行命令并获取输出结果。

这种方法适用于需要执行较为复杂的 JavaScript 代码,尤其是当你需要依赖 Node.js 生态系统(例如使用 NPM 包)时。

4. 使用 WebView(嵌入浏览器)

如果你的应用程序需要在桌面应用中显示 HTML 或 Web 内容,并且包含 JavaScript 代码,可以使用 WebView 库。WebView 可以嵌入一个小型浏览器,并执行 JavaScript 代码。

安装 webview

go get github.com/webview/webview

示例代码:

package main

import (
    "github.com/webview/webview"
)

func main() {
   
    // 创建一个 WebView 窗口并执行 JavaScript 代码
    webview.Open("Hello", `
        <html>
            <body>
                <script>
                    alert("Hello from JavaScript!");
                </script>
            </body>
        </html>
    `, 800, 600, true)
}

说明:

  • webview.Open 创建一个浏览器窗口并执行 HTML 和 JavaScript。
  • 这对于桌面应用程序非常有用,但对于仅需执行 JavaScript 代码的后端服务来说可能不太适用。

总结

  1. ottogoja:适用于需要在 Go 内部执行简单 JavaScript 代码的场景。
  2. os/exec:适用于需要运行 Node.js 脚本或更复杂的 JavaScript 代码的情况。
  3. WebView:适用于桌面应用程序,需要在嵌入式浏览器中运行 JavaScript。

根据你的需求,可以选择适合的方式来执行 JavaScript。如果你有具体的用例或场景,我可以帮助你进一步细化解决方案。

原文发表于:https://www.baihezi.com/post/223657.html

目录
相关文章
|
Go
Go 语言 errgroup 库的使用方式和实现原理
Go 语言 errgroup 库的使用方式和实现原理
201 0
|
5月前
|
JSON Dart 前端开发
JavaScript代码及其 Dart 对应代码
15 个 JavaScript 代码示例及其 Dart 对应代码
43 3
|
安全 Go
Golang 语言中的 defer 怎么使用?
Golang 语言中的 defer 怎么使用?
49 0
|
测试技术 Go
Golang 语言怎么编写测试代码?
Golang 语言怎么编写测试代码?
52 0
|
Go
Go 语言怎么使用变长参数函数?
Go 语言怎么使用变长参数函数?
55 0
|
7月前
|
安全 Go 开发者
Golang深入浅出之-Go语言模板(text/template):动态生成HTML
【4月更文挑战第25天】Go语言的`text/template`和`html/template`库提供动态HTML生成。本文介绍了模板基础,如基本语法和数据绑定,以及常见问题和易错点,如忘记转义、未初始化变量、复杂逻辑处理和错误处理。建议使用`html/template`防止XSS攻击,初始化数据结构,分离业务逻辑,并严谨处理错误。示例展示了条件判断和循环结构。通过遵循最佳实践,开发者能更安全、高效地生成HTML。
223 0
|
JSON JavaScript 前端开发
如何通过 JavaScript 运行用 Go 编写的 WebAssembly 模块? 下
如何通过 JavaScript 运行用 Go 编写的 WebAssembly 模块?
208 0
|
存储 人工智能 Java
深入了解Golang:基本语法与核心特性解析
深入了解Golang:基本语法与核心特性解析
|
JavaScript 程序员 Go
一图看懂编程语言迁移模式:终点站是Python、Go、JS
一图看懂编程语言迁移模式:终点站是Python、Go、JS
113 0
|
Go
Golang 语言函数的高级使用方式
Golang 语言函数的高级使用方式
50 0