第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/...
でできます。
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が復活してくれたらいいなぁ(チラチラ