gowasm-bindgen — ブラウザ向け型安全なGo/WASMバインディング

Tool

概要

gowasm-bindgenは、Goで書かれた関数をブラウザから型安全に呼び出せるようにするためのツールです。Goソースを解析して、TypeScriptの宣言ファイル(.d.ts)と、WASMバイナリに対するブリッジ用のコード(Go側とJS/TS側のGlueコード)を自動生成します。標準のGoツールチェーンで作るWASMは大型で同期実行のためUIをブロックしがちですが、gowasm-bindgenはTinyGoでのビルド最適化(約90KB gzippedを実現)や非同期ラッパーの生成を通じて、フロントエンドとの統合を現実的にします。CLIや設定を備え、TypeScript側で型情報を得ながら安全にGo関数を利用できます。

GitHub

リポジトリの統計情報

  • スター数: 2
  • フォーク数: 0
  • ウォッチャー数: 2
  • コミット数: 30
  • ファイル数: 22
  • メインの言語: Go

主な特徴

  • GoソースからTypeScript宣言(.d.ts)を自動生成し、フロントエンドでの型安全性を確保。
  • TinyGo対応によりWASMバイナリを小さく(約90KB gzipped)して配布コストを削減。
  • 非同期ラッパーを提供し、ブラウザのメインスレッドのブロッキングを回避。
  • CLI/自動生成フローにより既存Goコードから素早くTSバインディングを作成可能。

技術的なポイント

gowasm-bindgenの核は「Go関数をブラウザで型安全に呼び出すためのコード生成」にあります。主な技術要素は次の通りです。

  • コード生成: Goの関数シグネチャを解析して、対応するTypeScript型宣言を自動生成します。これにより、JS/TS側で従来anyでしか扱えなかったWASMエクスポートを、正確な型で呼び出せるようになります。生成物は宣言ファイルのほか、呼び出しを仲介する小さなラッパー(JS/TS)や必要なGo側のエントリポイントコードです。

  • 型マッピングとシリアライゼーション: プリミティブ型や構造体などのマッピングルールを用意し、JS⇄WASM間でデータをやり取りするための変換コードを生成します。複雑な値はシリアライズ(JSONなど)で受け渡すか、バッファ共有といった手法を取る設計が想定されており、用途に応じてトレードオフを選べます。

  • 非同期実行とUI保護: 標準のGo生成WASMは同期実行でメインスレッドをブロックしがちです。gowasm-bindgenは非同期ラッパー(Promiseベース)を提供し、実行をワーカーへ移すなどしてUIブロッキングを回避する設計をサポートします。これにより、フロントエンドとの親和性が高くなります。

  • TinyGoとの連携: TinyGoでビルドすることで、標準Goコンパイラよりも小さいランタイムを実現し、配布サイズを大幅に削減します。READMEにある通り、最適化された構成で約90KB(gzip)という現実的なサイズを達成できる点が特徴です。

  • 開発とリリース支援: リポジトリには.goreleaserやgolangciの設定が含まれており、CI/CDや品質チェックの導入を想定した構成になっています。また、サブモジュールやサンプルを通じて利用例を提供している可能性があります。

これらにより、フロントエンド開発者はTypeScriptの型補完と型チェックを得ながら、バックエンドロジックをGoで書き、効率的にブラウザ上で実行できる環境を手に入れられます。一方で、TinyGoの制約(ランタイム機能やreflectの挙動など)や、マシュアリングの性能・互換性は運用時に考慮が必要です。

プロジェクトの構成

主要なファイルとディレクトリ:

  • .github: dir
  • .gitignore: file
  • .gitmodules: file
  • .golangci.yml: file
  • .goreleaser.yml: file

…他 17 ファイル

まとめ

TinyGoとコード生成で小型かつ型安全なGo→WASM連携を実現する実用的なツール。

リポジトリ情報:

READMEの抜粋:

gowasm-bindgen

Type-safe Go in the browser.

Generate TypeScript declarations and Go WASM bindings from your Go source code. Ship 90KB gzipped binaries with TinyGo.

The Problem

Go WASM functions are invisible to TypeScript:

// TypeScript has no idea what this returns or accepts
const result = window.myGoFunction(???, ???);  // any

Standard Go WASM binaries are huge (~2.4MB), and WASM runs synchronously on the main thread, blocking your UI.

The Solution

gowa…