Mokelab Blog

Go で WebAssembly を書いてみよう

今回は Web 技術の 1 つである WebAssembly を Go で作り、JavaScript から使ってみます。

WebAssembly とは

WebAssembly とはブラウザでネイティブに近いコードを実行する技術です。MDN の概要ページはこちらです。 より高速に実行されるコードを JavaScript 以外の言語で記述することができます。

WebAssembly は .wasm という拡張子のファイルで、サーバーからは application/wasm という MimeType で提供します。C++や Rust などの言語で.wasm を生成することができますが、今回は Go で作ってみます。

本記事のサンプルはこちらにあります。デモサイトはこちらです。

環境構築

Go で WebAssembly を作るには、通常の Go 開発環境を用意するだけです。本記事では Go 1.13.4 を使用しました。また、$GOROOT に Go のインストール先が入っているものとして説明をします。

$ go version
go version go1.13.4 darwin/amd64

main.go を作る

早速 WebAssembly として動かすコードを Go で書きましょう。main.go としておなじみのコードを書きます。

package main

import (
  "fmt"
)

func main() {
  fmt.Printf("Hello wasm world!\n")
}

\n がないと標準出力が flush されず、動作してるか確認できなくなるので忘れずにつけておきましょう。

.wasm を作る

GOOS を js に、GOARCH を wasm にしてビルドします。

$ GOOS=js GOARCH=wasm go build -o docs/main.wasm

index.html を作る

wasm ファイルができたので、ブラウザで読み込んで実行させましょう。まずは index.html です。wasm_exec.js とアプリのコード(main.js)を読み込みます。

<html>
  <head>
    <title>WASM demo</title>
  </head>
  <body>
    <p>See your console.log()!</p>
    <script src="./wasm_exec.js"></script>
    <script type="module" src="./main.js"></script>
  </body>
</html>

wasm_exec.js は Go に付属しています。場所は$GOROOT/misc/wasm/wasm_exec.js です。コピーしておきましょう。なお wasm のビルドに使った Go のバージョンとは違うバージョンの wasm_exec.js(例えば Go 1.12.9 に付属している wasm_exec.js)を使うと実行時にエラーとなるので注意しましょう。

main.js を作る

最後に wasm を読み込んで実行する部分です。wasm_exec.js で提供されているクラスを利用します。

const go = new Go();
const exec = async () => {
  const result = await WebAssembly.instantiateStreaming(
    fetch("main.wasm"),
    go.importObject
  );
  go.run(result.instance);
};
exec();

fetch()で読み込んでいるので、実行するためにはサーバーが必要です。また、wasm の GET に対し、Content-type: application/wasm で返す必要があります。

実行すると、次のように Console.log()に wasm 内に記述したテキストが表示されます。

まとめ

Go で WebAssembly を記述・ビルド・実行までを説明しました。Go での開発環境があればすぐ始めれるので、みなさんもチャレンジしてみてください。

本サイトではサービス向上のため、Google Analyticsを導入しています。分析にはCookieを利用しています。