一日一技:在 Golang 中運行 JavaScript

攝影:產品經理

這個小黃魚 500 多一份

我們知道,在 Python 裏面,如果你要運行一段 JavaScript,你可以使用execJS這種第三方庫。那麼在 Golang 裏面,你想運行 JavaScript 的時候又應該怎麼辦呢?

最近我發現一個使用 Golang 開發的 JavaScript 引擎:Goja[1]。它實現了ES 5.1的所有語法和大部分的ES 6語法,比 Python 的execJS要厲害得多。在一定程度上和特定場景下,它可以完全替代 Chrome 的 V8 引擎。

我們來看看如使用它運行一段 JavaScript 代碼。首先,我來寫一段遞歸版的 JavaScript 代碼計算斐波那契數列:

function fib(n) {
    if (n === 1 || n === 2) {
        return 1 
    }
    return fib(n - 1) + fib(n - 2)
}

直接在瀏覽器上面運行的效果如下:

現在,我們來安裝這個Goja

go get github.com/dop251/goja

接下來我們在 Go 中運行 js 代碼:

package main

import (
    "fmt"

    "github.com/dop251/goja"
)

func main() {

    const script = `
    function fib(n) {
        if (n === 1 || n === 2) {
            return 1 
        }
        return fib(n - 1) + fib(n - 2)
    }
    `
    vm := goja.New()
    _, err := vm.RunString(script)
    if err != nil {
        fmt.Println("JS代碼有問題!")
        return
    }
    var fn func(int32) int32
    err = vm.ExportTo(vm.Get("fib")&fn)
    if err != nil {
        fmt.Println("Js函數映射到 Go 函數失敗!")
        return
    }
    fmt.Println("斐波那契數列第30項的值爲:", fn(30))
}

運行效果如下圖所示:

我們來解釋一下上面代碼的意思。請大家關注截圖中的代碼行號。第 19 行,我們創建了一個 JavaScript 的虛擬機。然後在第 20 行,把這個函數加載到了虛擬機當中。

第 25 行,我們創建了一個變量,這個變量是函數類型,這個函數接收一個 int32作爲參數,並返回另一個int32類型的數據。

第 26 行,我們把 Golang 裏面的這個函數變量與 JavaScript 裏面的函數fib關聯起來,這樣我們就能直接寫 Go 代碼來調用 JavaScript 代碼了。

第 31 行,我們像調用普通的 Go 函數一樣傳入參數,然後獲得結果。

有一些同學在做爬蟲的時候,需要運行一段 JavaScript 代碼來生成一段 token,那你不妨試一試Goja,它的速度肯定要比你用 Python 版本的快很多。

參考文獻

[1] Goja: https://github.com/dop251/goja

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/edEee9qsdQZrCPZIgJiEGQ