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

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

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

goja とは

https://github.com/dop251/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を実装しているパッケージがあります。

https://github.com/dop251/goja_nodejs

このパッケージの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が復活してくれたらいいなぁ(チラチラ


『 Go 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。