Node.jsからGo言語で生成したWebAssemblyを使う方法を解説。

TinyGoを使えばGoの関数を直接Node.jsから呼び出すことができる。

引数や返り値もJavaScriptで読み込むことができるので、ちょっとした重い計算処理などをWebAssembly化し、高速化することが可能

デフォルトのGoコンパイラでは、exportが出来ないので直接main関数以外の関数を呼び出すことは出来ません。(2022/11/26時点)
またこの記事で解説するコードとは少し異なるのでココを参照

2022/12/8 追記
stringを引数、返り値のように使う方法についても↓で解説しました
https://kajindowsxp.com/go-tinygo-webassembly-string/

ファイルを用意する

wasm.go
コメントで//export fugaと記載すると、Node.js側でfugaとして認識できるようになる。

package main

import (
	"fmt"
)

//export fuga
func hoge(a, b int) int {
	return a + b
}

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

main.js

"use strict";

require("./wasm_exec_tiny");

const go = new Go();

WebAssembly.instantiate(fs.readFileSync("./wasmbin"), go.importObject).then(function (obj) {
  let wasm = obj.instance;
  go.run(wasm);
  console.log(wasm.exports.fuga(2,3))
})

更に以下コマンドを実行し、wasm_exec_tiny.jsを準備する

cp $(tinygo env TINYGOROOT)/targets/wasm_exec.js wasm_exec_tiny.js

ビルド & 実行

以下コマンドでGoのWebAssemblyビルドを行う

tinygo build -o wasmbin -target wasm wasm.go

完了したらNode.jsを走らせてみる

$ node main.js
Hello World
5

go側で定義したhoge関数がwasm.exports.fuga(2,3)として呼び出され、足し算された5がコンソールに出力される。

githubリンク

この記事のソースコードは以下のリンクからも参照できる

https://github.com/kajikentaro/wasm-go-tinygo-sample/tree/master/tinygo

トラブルシューティング

Windows環境でtinygoのビルドを実行したときにerror: could not find wasm-opt, set the WASMOPT environment variable to overrideと言われた。
以下コマンドでbinaryenをインストールすることで解決。

scoop install binaryen

参考