Web・アプリ制作

GoでWebAssemblyをやってみた

AMBLでWebアプリケーションの開発を行っている萱沼です。好きな色は黄色です。

ウェブアプリケーションの進化とともに、JavaScriptがさまざまな用途で使用されるようになったことで、実行速度を補完する目的でWebAssembly(以下、Wasm)の活用が広がっています。

今回はWasmをGo言語で実装し、その仕組みに迫ります!

この記事は下記の方におススメです
Go言語を利用したことがある方/Go言語に興味がある方/Webアプリを実装したことがある方/Go言語の実行環境をPCに構築済みの方

実行環境

OSバージョン:macOS Ventura 13.4

Goバージョン:1.20.5

ディレクトリ構成
working_dir
├── go.mod
├── main.css
├── main.go
├── main.wasm
├── wasm_exec.html
└── wasm_exec.js

Wasmとは?

Wasmとは、コンピュータが理解しやすい形式に変換されたプログラムをウェブブラウザで実行するための新しい形式です。

通常、ウェブブラウザで実行されるコードは、JavaScriptという言語で書かれています。

ですが、Wasmは、JavaScriptとは異なる形式で、ウェブブラウザがより高速に処理できるように設計されています。

迅速に解読・実行できる点では、「機械語」のイメージに近いかもしれません。

Wasmの利点は、高速性と効率性です。大きな計算を必要とするアプリケーションやゲームなど、Wasmを利用することでウェブブラウザでもスムーズな動作が期待できます。

さらに、CやC++、Rustといった言語で書かれたプログラムをブラウザで実行することも可能になります。

それでは実際にGo言語を用いて、Wasmを実行してみましょう!

go.modの作成

適当なプロジェクトのディレクトリを作成し、go mod initを実行します。

$ go mod init app

wasm実行環境構築

Go言語で実行するためのサンプルが公式で用意されているので、それを利用します。

cpコマンドで2つのファイルをコピーします。

$ cp "$(go env GOROOT)/misc/wasm/wasm_exec.html" ./
$ cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" ./

htmlファイルの編集

コピーをした「wasm_exec.html」を以下のように編集します。

<!doctype html>
<!--
Copyright 2018 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
-->
<html>

<head>
	<meta charset="utf-8">
	<link rel="stylesheet" href="main.css">
	<title>Go wasm</title>
</head>

<body>
	<h1>Go wasm application</h1>
	<script src="wasm_exec.js"></script>
	<script>
		const go = new Go();
		let mod, inst;
		WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
			mod = result.module;
			inst = result.instance;
			document.getElementById("runButton").disabled = false;
		}).catch((err) => {
			console.error(err);
		});

		async function run() {
			// console.clear();
			await go.run(inst);
			inst = await WebAssembly.instantiate(mod, go.importObject); // reset instance
		}
	</script>

	<button onClick="run();" id="runButton" disabled>Run</button>
</body>

</html>

main.goの作成

main.goというファイルを作成し、以下の内容を記載します。

package main

import "fmt"

func main() {
	fmt.Println("Hello world.")
}

標準出力に「Hello world.」を表示するプログラムを作成します。

動作確認

作成したmain.goの動作確認をしてみましょう。

$ cd working_dir
$ go run main.go // Hello world.が標準出力に出力できていればOK

wasmファイルの作成

main.goがあるディレクトリで以下のコマンドを実行します。

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

「main.wasm」のファイル名でバイナリのファイルが作成されます。

実行

「wasm_exec.html」をブラウザで開きます。

すると、以下のような画面が開きます。

開発者ツールを開き、「Run」ボタンを押下すると、コンソールに「Hello world.」が出力されます。

コンソールに出力されている文字列は、「main.go」で出力するようにプログラムしたものです。これで完了です。

まとめ

Go言語を用いて、Wasmを実行してみました。

公式で用意されているものを用いて実装できますし、導入のハードルは低いのでぜひ実践してみてくださいね!

ちなみにGoではVectyやVuguなどのフレームワークもあります。

今回の記事ではコンソールに出力するのみでしたが、DOMを操作する際はそれらのフレームワークを利用したほうが開発しやすいと思います。

サンプルのコードもあるので、そちらにチャレンジしてみるのも面白いかもしれません。

GitHub – hexops/vecty: Vecty lets you build responsive and dynamic web frontends in Go using WebAssembly, competing with modern web frameworks like React & VueJS.

Vugu

参考:VectyでサンプルのTodoMVCを実行した様子

ABOUT ME
萱沼 広稀
Webアプリケーションエンジニア。 日々、新しい技術のキャッチアップに邁進しています!