在 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

相关文章
|
3月前
|
JavaScript
短小精悍的js代码
【10月更文挑战第17天】
145 58
|
5天前
|
人工智能 程序员 UED
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
|
4天前
|
前端开发 JavaScript
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
|
6天前
|
人工智能 JavaScript 前端开发
一段 JavaScript 代码,集成网站AI语音助手
根据本教程,只需通过白屏化的界面操作,即可快速构建一个专属的AI智能体。
|
1月前
|
运维 监控 Cloud Native
一行代码都不改,Golang 应用链路指标日志全知道
本文将通过阿里云开源的 Golang Agent,帮助用户实现“一行代码都不改”就能获取到应用产生的各种观测数据,同时提升运维团队和研发团队的幸福感。
|
1月前
|
存储 网络架构
Next.js 实战 (四):i18n 国际化的最优方案实践
这篇文章介绍了Next.js国际化方案,作者对比了网上常见的方案并提出了自己的需求:不破坏应用程序的目录结构和路由。文章推荐使用next-intl库来实现国际化,并提供了详细的安装步骤和代码示例。作者实现了国际化切换时不改变路由,并把当前语言的key存储到浏览器cookie中,使得刷新浏览器后语言不会失效。最后,文章总结了这种国际化方案的优势,并提供Github仓库链接供读者参考。
|
2月前
|
JavaScript
原生js炫酷随机抽奖中奖效果代码
原生js随机抽奖是一个炫酷的根据数据随机抽奖的代码,该网页可进行随机抽取一个数据,页面动画高科技、炫酷感觉的随机抽奖效果,简单好用,欢迎下载!
70 3
|
2月前
|
JavaScript 前端开发 开发者
如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码,包括安装插件、配置 ESLint 和 Prettier 以及 VSCode 设置的具体步骤
随着前端开发技术的快速发展,代码规范和格式化工具变得尤为重要。本文介绍了如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码,包括安装插件、配置 ESLint 和 Prettier 以及 VSCode 设置的具体步骤。通过这些工具,可以显著提升编码效率和代码质量。
671 4
|
2月前
|
JSON 移动开发 数据格式
html5+css3+js移动端带歌词音乐播放器代码
音乐播放器特效是一款html5+css3+js制作的手机移动端音乐播放器代码,带歌词显示。包括支持单曲循环,歌词显示,歌曲搜索,音量控制,列表循环等功能。利用json获取音乐歌单和歌词,基于html5 audio属性手机音乐播放器代码。
159 6