Go での WebAssembly の紹介

Go での WebAssembly の紹介

WebAssembly は、Javascript の相互運用性を備えたブラウザーでより多くの言語を実行するために設計された最新のテクノロジの 1 つです。

WebAssembly (WASM) は、プラットフォームに依存しない、スタックベースの仮想マシン用のバイナリ命令形式であり、プログラミング言語を有効にする環境 (つまり、Web およびサーバー アプリ) で実行するための移植可能なコンパイル ターゲットとして設計されています。

WASM を使用すると、Go を含むいくつかのプログラミング言語をブラウザーで実行し、言語の機能を活用できます。また、Web 上の Javascript との相互運用も可能です。

Go で WebAssembly を使い始める

Go は、Go アプリケーションで WebAssembly を使用するための最高のサポートを提供します。いくつかの構成を行い、Go コードを WebAssembly にコンパイルするだけで済みます。

Go コードを WebAssembly にトランスパイルするには、いくつかの構成を行う必要があります。Go アーキテクチャの GOARCH環境変数をwasmに変更し、Go オペレーティング システムのGOOS変数をjsに変更する必要があります。

これらの構成を行うには、作業ディレクトリのターミナルでこのコマンドを実行します。

Set GOARCH=wasm GOOS=js

次のステップは、Go コードを WebAssembly .wasmファイルにトランスパイルすることです。このコマンドを実行して、main.goファイルを lib.wasm という名前のファイルにトランスパイルします。

go build -o lib.wasm main.go

コマンドを実行すると、作業ディレクトリにlib.wasmが見つかります。

Web ページで NodeJS を使用して WebAssembly ファイルを実行するには、Go インストールに付属する WebAssembly ファイルを作業ディレクトリにコピーする必要があります。

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

このコマンドはwasm_exec.jsファイルを作業ディレクトリにコピーし、アプリケーションへのエントリ ポイントとして機能します。

wasm_exec.jsスクリプトを使用して、Go で WASM ファイルを実行し、DOM API 呼び出しを行うことができるようになりました。

node wasm_exec.js main.wasm

Web サーバーを起動して Web サイトをホストする

Go 作成者からのこのコードを作業ディレクトリの HTML ファイルに追加して、instantiateStreamingメソッドで WebAssembly データ ストリームをインスタンス化します。

<!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" />
    <title>Go wasm</title>
</head>

<body>
<script src="wasm_exec.js"></script>

<script>
    if (!WebAssembly.instantiateStreaming) {
        // polyfill
        WebAssembly.instantiateStreaming = async (resp, importObject) => {
            const source = await (await resp).arrayBuffer();
            return await WebAssembly.instantiate(source, importObject);
        };
    }

    const go = new Go();

    let mod, inst;

    WebAssembly.instantiateStreaming(fetch("lib.wasm"), go.importObject).then(
        result => {
            mod = result.module;
            inst = result.instance;
            document.getElementById("runButton").disabled = false;
        }
    );

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

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

HTML コードは、Go コードを Web ページに接続する WebAssembly ストリームをインスタンス化するための Go 作成者からのものです。

ページを実行するための Web サーバーの起動

httpパッケージを使用してサーバーをセットアップします。httpパッケージと、考えられるエラーをコンソールに記録するためのログパッケージをインポートします。

import (
    "log"
    "net/http"
)

サーバーアドレスの変数と、そのアドレスで提供するファイルのディレクトリを宣言できます。

var (
    serverAddr = ":8080"
    directory = "."
)

httpパッケージのFileServerメソッドを使用して、指定したディレクトリ内のファイルを提供できます。FileServerメソッドはディレクトリを受け取り、ファイル サーバー インスタンスを返します。

func main() {
    serveFiles: = http.FileServer(http.Dir(directory))
    if err: = http.ListenAndServe(serverAddr, serveFiles); err! = nil {
        log.Fatalln(err)
}
}

メイン関数では、ファイル サーバー インスタンス変数を宣言して、ルート ディレクトリ内のファイルを提供しました。ListenAndServeメソッドは、指定されたポートの指定されたディレクトリ内のファイルを提供します

WASM をブラウザにロードした結果

Go の WebAssembly 関数

Go は、JS 関数を呼び出し、syscall/jsパッケージで DOM と対話するための機能を提供します。

jsパッケージは、 js/wasmアーキテクチャー上の WebAssembly ホスト環境へのアクセスを提供します。パッケージにアクセスして使用するには、開発環境をGOARCH=wasm GOOS=jsに設定する必要があります。

js パッケージ ドキュメント プレビュー

パッケージ内のさまざまなメソッドを使用して、Web ページを操作できます。関数をjsパッケージに登録する方法は次のとおりです。

// function definition
func print(this js.Value, i []js.Value) interface{} {
    return js.ValueOf(i[:])
}

コールバック関数としての登録時のprint関数は、関数に渡されたデータをブラウザ コンソールに出力します。

jsパッケージのGlobalメソッドのSetメソッドでコールバック関数を登録できます。Setメソッドは、関数識別子とコールバック関数インスタンスを受け取ります。

func RegisterCallbackFunctions() {
    js.Global().Set("print", js.FuncOf(print))
}

RegisterCallbackFunctionsメソッドは、ブラウザー コンソールで使用できるコールバック関数として印刷関数を登録します

WebAssembly は、Go を含む多くの言語で実験的な機能です

WebAssembly の機能は、特にその言語が最近 W3C 標準になったため、多くの言語にとって比較的新しい機能です。jsパッケージは実験的なものであり、このパッケージは Go 互換性の約束から除外されています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です