在 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
AI 代码解读

示例代码:

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!
}
AI 代码解读

说明:

  • 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
AI 代码解读

示例代码:

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!
}
AI 代码解读

说明:

  • 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))
}
AI 代码解读

说明:

  • 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
AI 代码解读

示例代码:

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)
}
AI 代码解读

说明:

  • 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

目录
打赏
0
14
15
2
26
分享
相关文章
JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
Array.sort() 是一个功能强大的方法,通过自定义的比较函数,可以处理各种复杂的排序逻辑。无论是简单的数字排序,还是多字段、嵌套对象、分组排序等高级应用,Array.sort() 都能胜任。同时,通过性能优化技巧(如映射排序)和结合其他数组方法(如 reduce),Array.sort() 可以用来实现高效的数据处理逻辑。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
【通义灵码】三句话生成P5.js粒子特效代码,人人都可以做交互式数字艺术
我发掘出的通义灵码AI程序员新玩法:三句话生成P5.js粒子特效代码,人人都可以做交互式数字艺术
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
157 21
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
三句话生成 P5.js 粒子特效代码,人人都可以做交互式数字艺术
短短几分钟,两个完全不懂P5.js的人类,和通义灵码AI程序员一起,共同完成了有真实物理引擎和碰撞检测的3D仿真动画。人类扮演的角色更像产品经理和架构师,提出开发需求和迭代修改方案,而AI的作用更像码农,任劳任怨,熟练用各种编程语言完成技术底层的脏活累活。这只是AI编程的冰山一角,未来,每一个艺术家都能快速做出自己的创意原型,每一个数学老师都能轻松做出自己的教学动画。
20 个 JavaScript 简化技巧,让你的代码更上一层楼!
JavaScript 既灵活又强大,掌握以下20个技巧可助你编写更简洁高效的代码
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
75 14
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
通过array.some()实现权限检查、表单验证、库存管理、内容审查和数据处理;js数组元素检查的方法,some()的使用详解,array.some与array.every的区别(附实际应用代码)
array.some()可以用来权限检查、表单验证、库存管理、内容审查和数据处理等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
通过array.every()实现数据验证、权限检查和一致性检查;js数组元素检查的方法,every()的使用详解,array.some与array.every的区别(附实际应用代码)
array.every()可以用来数据验证、权限检查、一致性检查等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
JavaScript中通过array.filter()实现数组的数据筛选、数据清洗和链式调用,JS中数组过滤器的使用详解(附实际应用代码)
用array.filter()来实现数据筛选、数据清洗和链式调用,相对于for循环更加清晰,语义化强,能显著提升代码的可读性和可维护性。博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

热门文章

最新文章