[Go]Webassembyのチュートリアル
GoでWebassemblyを使うためのチュートリアルとやってみた。
まずは公式のwikiを見ながら初めて、その中で紹介されてた簡単な計算機(足し算と引き算)の作成まで。
Hello world!
Goで書いたコードをビルドする。
コードは以下の通り、非常に簡単。"Hello world!"を出力するだけ。
package main
func main() {
println("Hello world!")
}
GOOS=js GOARCH=wasm
"GOOS=js"、"GOARCH=wasm"を指定して、ビルドしてwasmファイル(といえばいいのか?)が出来上がる。
index.htmlを作成して、ビルドしたwasmファイルをロードする。
記載は以下の通り。とりあえず公式wikiの記載通り。
<html>
<head>
<meta charset="utf-8">
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("lib.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
</script>
</head>
<body></body>
</html>
wasm_exec.jsファイルは、Goがインストールされているディレクトリの "misc/wasm"以下にあるので、index.htmlと同じディレクトリにコピーしておく。
HTTPサーバを起動する。
作業しているディレクトリに、server.goを以下の内容で作成し、起動する。
package main
import (
"flag"
"log"
"net/http"
)
var (
listen = flag.String("listen", ":8080", "Listen address")
dir = flag.String("dir", ".", "directory to server")
)
func main() {
flag.Parse()
log.Printf("listening on %q...", *listen)
log.Fatal(http.ListenAndServe(*listen, http.FileServer(http.Dir(*dir))))
}
ブラウザから http://localhost:8080/index.html にアクセスすれば、コンソールに"Hello world!"と出力されているはず。
関数の使用
main.goを修正して、足し算用の関数を作成し、それをjsから呼び出せるようにする。
package main
import (
"fmt"
"syscall/js"
)
func add(this js.Value, i []js.Value) interface{} {
js.Global().Set("output", js.ValueOf(i[0].Int()+i[1].Int()))
fmt.Printf("%v\n", js.ValueOf(i[0].Int()+i[1].Int()))
return nil
}
func registerCallbacks() {
js.Global().Set("add", js.FuncOf(add))
}
func main() {
c := make(chan struct{}, 0)
println("Go WebAssembly Initialized")
registerCallbacks()
<-c
}
やっていることは、関数を定義してそれを"add"という関数名でjsから呼び出せるようにすること。
チュートリアルでは、関数の登録時に"js.NewCallback()"という関数を使用していたけど、現在は"js.FuncOf()"を使って登録するみたい。
※syscall/jsパッケージは冒頭に「This package is EXPERIMENTAL. Its current scope is only to allow tests to run, but not yet to provide a comprehensive API for users. It is exempt from the Go compatibility promise.」と注意書きがされている。
ビルドして、ブラウザをリロードする。
コンソールでadd関数が使用できるようになっていればOK。
DOMを操作
index.html を修正して、パラメータ二つと計算結果表示用のテキストボックスを追加する。Add/Subtructボタンも追加して、押したら計算wasmの関数を呼び出す。<body>
<body>
<input type="text" id="v1" />
<input type="text" id="v2" />
<button onClick="add('v1', 'v2', 'result');" id="addButton">Add</button>
<button onClick="subtract('v1', 'v2', 'result');" id="subtractButton">Subtract</button>
<input type="text" id="result" />
</body>
main.goでDOMを参照して、パラメータの値を取得して、結果を出力する。
DOMを参照する処理をそのままGoで書いているだけという感じ。。。
以下はAdd関数。
func add(this js.Value, i []js.Value) interface{} {
value1 := js.Global().Get("document").Call("getElementById", i[0].String()).Get("value").String()
value2 := js.Global().Get("document").Call("getElementById", i[1].String()).Get("value").String()
int1, _ := strconv.Atoi(value1)
int2, _ := strconv.Atoi(value2)
js.Global().Get("document").Call("getElementById", i[2].String()).Set("value", int1+int2)
return nil
}
できた画面
感想など
・Goでwasmを使う場合のイメージが少しわかった。
・DOMの操作の仕方もわかった。
・大変そう。うまくやるライブラリがあるのだろうと思う。
・次はインタプリタをwasmで動かすというのをやってみようと思う。
この記事が気に入ったらサポートをしてみませんか?