Open2

Golang WASM + node 試すメモ

knaka Tech-Blogknaka Tech-Blog

概要

  • Golang WASM の例です。

[ 公開 2025/07/08 ]


環境

  • ubunutu
  • go version go1.24.4 linux/amd64
  • node 20

準備

  • wasm_exec.js 必要
  • (go env GOROOT)/lib 下。ありそう。
  • ubuntu の場合。 /usr/local/go/lib/wasm/
  • wasm_exec_node.js , 作業フォルダにコピー

$ ll /usr/local/go/lib/wasm/
total 40
drwxr-xr-x 2 root root  4096 May 30 04:37 ./
drwxr-xr-x 5 root root  4096 May 30 04:37 ../
-rwxr-xr-x 1 root root   603 May 30 04:37 go_js_wasm_exec*
-rwxr-xr-x 1 root root   797 May 30 04:37 go_wasip1_wasm_exec*
-rw-r--r-- 1 root root 16992 May 30 04:37 wasm_exec.js
-rw-r--r-- 1 root root  1186 May 30 04:37 wasm_exec_node.js

  • main.go
  • echo関数の例。

package main

import (
  "fmt"
  "syscall/js"
)

func echo(this js.Value, args []js.Value) interface{} {
    fmt.Println("#start-echo")
    var s = args[0].String()
    fmt.Println(s)
    return "Hello, " + args[0].String()
}

func main() {
    js.Global().Set("echo", js.FuncOf(echo))
    select{} // 永続的にブロック
}



  • テスト用コード
const fs = require('fs');
const util = require('util');

// Node.js環境でGo WASMを動作させるための準備
global.TextEncoder = util.TextEncoder;
global.TextDecoder = util.TextDecoder;
global.performance = require('perf_hooks').performance;

// グルーコードを読み込む
require('./wasm_exec.js');

async function run() {
  // Goのインスタンスを作成
  const go = new Go();

  // WASMファイルを読み込み、インスタンス化
  const wasmBytes = fs.readFileSync('./main.wasm');
  const { instance } = await WebAssembly.instantiate(wasmBytes, go.importObject);

  // GoのWASMを実行開始
  // これにより、Goのmain関数が実行され、関数がグローバルにセットされる
  go.run(instance);

  // Go側でグローバルにセットした'add'関数を呼び出す
  const result = global.echo("hoge222");
  console.log('Result from Go:', result); // => Result from Go: 35
}

run();

  • 実行すると、
  • .echo(WASM) から、文字表示される。
knaka Tech-Blogknaka Tech-Blog

Vecel デプロイ、Golang WASM

  • Go WASM + express 構成になります。

環境

  • ubunutu
  • go version go1.24.4 linux/amd64
  • node 20

書いたコード

https://gist.github.com/kuc-arc-f/10a7f1391ce163b686e422d47d5e1b8e


  • start
npm run build:wasm
npm run dev


  • tree
  • dist/* は、buildが生成します。
  • wasm_exec.js は、前回と同様です。
$ tree .
.
├── dist
│   ├── empty.txt
│   ├── index.js
│   ├── main.wasm
│   └── wasm_exec.js
├── go.mod
├── main.go
├── main.wasm
├── package.json
├── src
│   └── index.js
├── vercel.json
└── wasm_exec.js

  • main.go 前回と、ほぼ同様
  • src/index.js

const fs = require('fs');
const util = require('util');

// Node.js環境でGo WASMを動作させるための準備
global.TextEncoder = util.TextEncoder;
global.TextDecoder = util.TextDecoder;
global.performance = require('perf_hooks').performance;
const express = require('express');
const app = express();
const port = 3000;

// POST の JSON を読み取る
app.use(express.json());

console.log("dirname=", __dirname);

// グルーコードを読み込む
require(__dirname + '/wasm_exec.js');

const go = new Go();
const wasmBytes = fs.readFileSync(__dirname + '/main.wasm');

app.get('/', async (req, res) => {
  const { instance } = await WebAssembly.instantiate(wasmBytes, go.importObject);
  go.run(instance);
  const result = global.echo("hoge222");
  console.log('Result from Go:', result);
  res.send(result);
});

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});


  • vercel は、Github経由でデプロイしました。
  • vercel.json 使用しました。