Go WebAssemblyでブラウザ上でGoを実行する その3 Javascript側からGoの関数を呼び出す
前回の記事「Go WebAssemblyでブラウザ上でGoを実行する その2 Go側からJavascriptを操作する」では、Go側からJavascriptを操作してみました。
今回はJavascript側からGoの関数を呼び出してみようと思います。
Goでメソッドを定義する
簡単な例として以下を定義しました。
package main
import "fmt"
type Money int
func (m *Money) Add(v Money) {
*m += v
}
func (m *Money) Print() {
fmt.Println(*m)
}
func main() {
m := Money(100)
m.Add(Money(200))
m.Print()
}
実行してみるとこんな感じです。
$ go run main.go
300
ここで定義したAddとPrintをjs側から呼べるようにしていきます。
js側でGoのメソッドが呼び出せるようにWebAssembly化する
package main
import (
"fmt"
"syscall/js"
)
type Money int
// wasmから呼び出す為に引数をと返り値を変更している
// 引数 this js.Value, args []js.Value
// 返り値 any
func (m *Money) Add(this js.Value, args []js.Value) any {
// 引数の値を直接使えないので整数型に変換
v := Money(args[0].Int())
*m += v
return nil
}
func (m *Money) Print(this js.Value, args []js.Value) any {
fmt.Println(*m)
return nil
}
func main() {
c := make(chan struct{}, 0)
m := Money(100)
// メソッドをjavascript側に登録する処理
js.Global().Set("money", js.ValueOf(
map[string]any{
"Print": js.FuncOf(m.Print),
"Add": js.FuncOf(m.Add),
},
))
// main関数が終了しないようにチャネルを使って処理をブロック
<-c
}
このファイルをwasmでビルドします。
$ GOOS=js GOARCH=wasm go build -o money.wasm
HTMLに埋め込んで実際に動かしてみる
ビルドしたmoney.wasmとwasm_exec.js、index.htmlを1つのディレクトリにまとめます。
docs$ ls
index.html money.wasm wasm_exec.js
index.htmlの内容は以下になります。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Go wasm sample 3</title>
<script src="wasm_exec.js"></script>
</head>
<body>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("money.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
</script>
<button onClick="money.print();" id="runButton" >print</button><br>
<button onClick="money.add(100)" id="runButton">add</button><br>
</body>
</html>
この状態で1つ上の階層でサーバを作成して起動させます。
main.go
package main
import (
"log"
"net/http"
)
func main() {
port := "8080"
http.Handle("/", http.FileServer(http.Dir("./docs/")))
log.Printf("Listen on port: %s", port)
http.ListenAndServe(":"+port, nil)
}
サーバ起動
$ go run main.go
2022/08/17 10:22:38 Listen on port: 8080
挙動確認
ブラウザにアクセスして挙動を確認します。
以下はprintを1回、addを2回、printを1回クリックした状態です。
Javascirpt側からGoのメソッドが呼び出せました!
さいごに
比較的簡単にJavascript側からGoのメソッドを呼び出すことができました。 Go側で圧縮や変換処理など重めな処理を受け持つ場合など有効なのではないでしょうか? ただ、メソッドの引数と返り値をわざわざ変換しないといけないのでテストを書く際に 工夫しないと若干面倒な気もしますね。。
まだまだGoのWebAssemblyはバイナリの大きさなど課題がある状態のようですが、 ポータビリティも高く、場合によってはかなり有用なケースもあると思います。 今後も動向に注目したいと思います。
この記事を書いた人
- 創造性を最大限に発揮するとともに、インターネットに代表されるITを活用し、みんなの生活が便利で、豊かで、楽しいものになるようなサービスやコンテンツを考え、創り出し提供しています。
この執筆者の最新記事
関連記事
最新記事
FOLLOW US
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー