Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
22
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

gojaを使ってGoでJavaScriptの実行を試してみた

第2のドワンゴ Advent Calendar 2016の3日目の記事です。

来年使い倒そうと思ってるgojaについて紹介しようと思います。

goja とは

gojaはEcmaScript5.1をGoで実装しているライブラリです。
GoでJavaScriptを実行するメリットとしてプラグインにJavaScriptを使えたりサーバーサイドレンダリングに使えるのではないかなと思います。

インストール

Goを入れていればgo get github.com/dop251/gojaでインストールできます。

Hello World

gojaのHello Worldです。
スクリプトで最後に実行した行の戻り値がRunStringの戻り値として取得できます。

package main

import (
    "fmt"

    "github.com/dop251/goja"
)

func main() {
    vm := goja.New()
    v, err := vm.RunString(`2+2`)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%T, %#v\n", v, v) // Output: goja.valueInt, 4
}

Goとの値のやり取り

Setを使うことでスクリプト実行前に変数を定義することができます。

package main

import (
    "fmt"

    "github.com/dop251/goja"
)

func main() {
    vm := goja.New()
    x, y := 5, 7
    vm.Set("x", x)
    vm.Set("y", y)
    v, err := vm.RunString(`x+y`)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%T, %#v\n", v, v) // Output: goja.valueInt, 7
}

関数も同じ様にセットすることができます。

package main

import (
    "fmt"

    "github.com/dop251/goja"
)

func Sum(x, y int) int {
    return x + y
}

func main() {
    vm := goja.New()
    vm.Set("sum", Sum)
    v, err := vm.RunString(`sum(9, 4)`)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%T, %#v\n", v, v) // Output: goja.valueInt, 13
}

逆にJavaScriptで定義した変数をGoに渡すこともできます。
その場合はGetを使います。

package main

import (
    "fmt"

    "github.com/dop251/goja"
)

func main() {
    vm := goja.New()
    _, err := vm.RunString(`
        var result = 8 + 7
    `)
    if err != nil {
        panic(err)
    }

    v := vm.Get("result")

    fmt.Printf("%T, %#v\n", v, v) // Output: goja.valueInt, 15
}

変数だけではなく関数もJavaScriptで定義してGoで呼び出すこともできます。

package main

import (
    "fmt"

    "github.com/dop251/goja"
)

func main() {
    vm := goja.New()
    _, err := vm.RunString(`
        function sum(x, y) {
            return x + y
        }
    `)
    if err != nil {
        panic(err)
    }

    var v goja.Value
    if sum, ok := goja.AssertFunction(vm.Get("sum")); ok {
        v, err = sum(goja.Undefined(), vm.ToValue(4), vm.ToValue(10))
        if err != nil {
            panic(err)
        }
    }

    fmt.Printf("%T, %#v\n", v, v) // Output: goja.valueInt, 14
}

モジュールの読み込み

サイドプロジェクトとしてNode.jsのrequireとconsoleを実装しているパッケージがあります。

このパッケージのrequireを使うことでモジュール読み込みができます。
インストールはgo get github.com/dop251/goja_nodejs/...でできます。

sum.js
module.exports = function sum(x, y) {
    return x + y
}

モジュールをJavaScriptから呼び出すなら以下のように。

package main

import (
    "fmt"

    "github.com/dop251/goja"
    "github.com/dop251/goja_nodejs/require"
)

func main() {
    registry := new(require.Registry)

    vm := goja.New()
    registry.Enable(vm)
    v, err := vm.RunString(`
        var sum = require('./sum.js')
        sum(10, 5)
    `)

    if err != nil {
        panic(err)
    }

    fmt.Printf("%T, %#v\n", v, v) // Output: goja.valueInt, 15
}

モジュールをGoで呼び出すなら以下のようになります。

package main

import (
    "fmt"

    "github.com/dop251/goja"
    "github.com/dop251/goja_nodejs/require"
)

func main() {
    registry := new(require.Registry)

    vm := goja.New()
    rm := registry.Enable(vm)

    var v goja.Value
    if sum, err := rm.Require("sum.js"); err != nil {
        panic(err)
    } else {
        if sum, ok := goja.AssertFunction(sum); ok {
            v, err = sum(goja.Undefined(), vm.ToValue(6), vm.ToValue(7))
            if err != nil {
                panic(err)
            }
        }
    }

    fmt.Printf("%T, %#v\n", v, v) // Output: goja.valueInt, 13
}

まとめ

gojaを使えば手軽にJavaScriptを組み込むことができました。
ただsetTimeoutなどvue.jsでサーバーサイドレンダリングをしようと思うと
実装しなければならないものが多くてちょっと間に合わなかったので
来年こそはGoでSSRしたいと思います。

あと僕がGoを触るキッカケにもなったdwanGoが復活してくれたらいいなぁ(チラチラ

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
22
Help us understand the problem. What are the problem?