概要
WebAssembly は主にブラウザで動作する言語でバイトコードを使うため JavaScript よりも高速に動作します
また golang や Rust などサーバサイドのコードから .wasm と呼ばれるコンパイルされた WebAssembly コードを吐き出すことができこれがブラウザで動作します
つまり golang や Rust のコードがブラウザで動かせるような技術になります
今回は HelloWorld をやってみました
環境
- macOS 11.6
- golang 1.17
- Chrome 94.0.4606.71
golang のコード
まずは普通に golang のコードを書いてみます
とりあえず「Hello」と出力するだけのコードを記載します
- vim main.go
package main
import "fmt"
func main() {
fmt.Println("Hello, WebAssembly!")
}
.wasm ファイルを作成する
go build する際にいくつかのオプションを指定するだけで OK です
- GOOS=js GOARCH=wasm go build -o main.wasm
これで main.wasm というファイルが作成されています
% ls -l main.wasm
-rwxr-xr-x 1 hawk staff 2020036 10 14 16:22 main.was
index.html の作成
作成した .wasm ファイルをブラウザ上で動かします
main.wasm と index.html は同じディレクトリ上に配置してください
- vim index.html
<html>
<head>
<meta charset="utf-8">
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
</script>
</head>
<body></body>
</html>
wasm_exec.js の配置
golang を brew でインストールしているのであれば以下のようなパスにあるはずです
コピーして同じディレクトリに配置します
- cp /usr/local/Cellar/go/1.17/libexec/misc/wasm/wasm_exec.js .
動作確認
サーバを立てましょう
なんでも OK です
今回は Python を使います
- python3.9 -m http.server 8000
これでブラウザで localhost:8000 にアクセスしブラウザのコンソール情報を見ると以下のようにメッセージが表示されているのが確認できると思います
DOM を操作する
syscall/js を使うと golang から dom を操作できます
DOM は Get/Set で取得、設定ができます
DOM のメソッドをコールしたい場合は Call() を使います
DOM から取得できる値はすべて js パッケージの型として取得できるので golang で扱う場合には型の変換が必要です
main では WebAssembly 上で golang が終了しないようにチャネルを作成しています
HTML 側で作成したボタンがクリックされたときにコールされるメソッドを golang 側に実装します
今回は countup というメソッドが呼ばれるようにしかつその結果は id=counter の div タグに設定するようにしています
- vim main.go
package main
import (
"strconv"
"syscall/js"
)
func countup(this js.Value, i []js.Value) interface{} {
c := js.Global().Get("document").Call("getElementById", "counter").Get("textContent")
current, _ := strconv.Atoi(c.String())
js.Global().Get("document").Call("getElementById", "counter").Set("textContent", current+1)
return 0
}
func registerCallbacks() {
js.Global().Set("countup", js.FuncOf(countup))
}
func main() {
c := make(chan struct{}, 0)
registerCallbacks()
<-c
}
HTML 側も少しだけ修正します
ボタンと結果を表示する div を追加するだけです
- vim index.html
<html>
<head>
<meta charset="utf-8">
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
</script>
</head>
<body>
<div id="counter">0</div>
<button onClick="countup()">up</button>
</body>
</html>
これで再度ビルドして python で動作確認するとちゃんとカウントアップボタンが動作することが確認できると思います
- GOOS=js GOARCH=wasm go build -o main.wasm
- python3.9 -m http.server 8000
最後に
golang で WebAssembly に入門してみました
現在だと開発もかなり進んでおりドキュメントも豊富なので簡単に開発できると思います
WebAssembly を直接書くのは面倒なので golang に慣れている人はこの方法を使うと簡単に WebAssembly を使うことができると思います
WebAssembly で有名な Rust も同じような感じだと思います
0 件のコメント:
コメントを投稿