1 ポイント 投稿者 GN⁺ 2025-02-16 | 3件のコメント | WhatsAppで共有
  • Go 1.24でWebAssembly(Wasm)関連機能が拡張
  • go:wasmexport ディレクティブが追加され、Wasmモジュールの外部からGo関数を呼び出せるようになった
  • WASI向けの「reactor」ビルドモードにも対応し、長時間アクティブな状態でコードを実行できるようになった
  • これにより、Wasm環境でGoアプリケーションをより柔軟に拡張できる可能性が開かれた

WebAssembly and the WebAssembly System Interface

  • WebAssemblyは、Webブラウザで高性能な低レベルコードを実行するために作られたバイナリフォーマット
  • 現在はブラウザ外でも幅広く活用されており、WebAssembly System Interface(WASI)を通じてシステムリソースと相互作用できる
  • Goはバージョン1.11で js/wasm ポートによりWasmコンパイルをサポートし始め、1.21では新しい GOOS=wasip1 ポートによって WASI Preview 1 のシステムコールAPIを対象とする新たなポートを追加

go:wasmexport を使ったGo関数のWasmエクスポート

  • Go 1.24で新たに追加された go:wasmexport ディレクティブにより、Go関数をWasmモジュール外部から呼び出せるよう export として公開できる
  • 例: //go:wasmexport add のように宣言して関数を書けば、Wasmホストがその関数を呼び出せる
  • これはcgoの export ディレクティブに似ているが、よりシンプルなメカニズムで実装されている

Building a WASI Reactor

  • WASI の「reactor」は、継続的に動作し、イベントやリクエストに応答できるWebAssemblyモジュールを意味する
  • Go 1.24では -buildmode=c-shared オプションを使って WASI reactor ビルドをサポート
  • このビルドフラグはリンカに対し、_start 関数(コマンドモジュールのエントリポイント)を生成せず、代わりに _initialize 関数を生成するよう指示する
    • reactor は _initialize 関数によって初期化され、main 関数の代わりにまずこの関数を呼び出す必要がある
  • Wazero のようなランタイムと組み合わせると、_initialize 呼び出し後に export された関数を必要なだけ再呼び出しできる
  • この方式は、アプリケーションのプラグインや拡張機構としてWasmを活用する環境で有用

ホストとクライアント間のリッチな型サポート

  • Go 1.24では go:wasmimport で呼び出される関数の引数・戻り値型に対する制約が緩和
  • たとえば、bool、string、int32 ポインタ、構造体ポインタなどを渡せる
    • ただし、64ビット環境と32ビット環境の違いなどにより、依然として制限は存在する
  • これにより、Go Wasmアプリケーションをより自然かつ便利に書けるようになり、不必要な型変換を排除できる

制限事項

  • Wasmは並列処理のないシングルスレッドアーキテクチャ
  • go:wasmexport 関数は新しいゴルーチンを生成できるが、バックグラウンドゴルーチンを生成する関数は、go:wasmexport 関数が戻った後、GoベースのWasmモジュールが再度呼び出されるまで実行を継続しない
  • 一部の型制約は緩和されたが、依然として go:wasmimport および go:wasmexport 関数とともに使用できる型には制限がある
    • ポインタを含む複合型の受け渡しには、まだ制約が存在する

結論

  • Go 1.24の WASI reactor ビルドと go:wasmexport 機能の追加は、GoのWasmエコシステムを大きく広げる改善
  • これにより開発者は、より多様なGoベースのWasmアプリケーションを作れるようになり、WasmエコシステムにおけるGoの新たな可能性を開く

3件のコメント

 
click 2025-02-16

Wasm/gcが広く導入される前は、gcのない言語でwasmターゲットを開発するのがよさそうです

 
xguru 2025-02-16

Go 1.24 リリースでは簡単に触れられているだけですが、はるかに重要なアップデートですね。

 
GN⁺ 2025-02-16
Hacker Newsの意見
  • Goで生成されたWASMバイナリには非常に大きいという問題がある。TinyGoはこれを克服するが、コンパイル速度が遅く、ライブラリ選定にも注意が必要だ。両方を乗り越えるにはかなりの忍耐が必要になる

    • Cloudflare WorkersでGo WASMを試そうとすると、バイナリサイズのために有料プランが必要になる
    • 最後に試したときは hello-world は動かせたが、より複雑なものはサイズ制限を超えてしまった
    • 残念な状況だ
  • 驚くべきことだ。覚えておくべき点:

    • GoのWebAssembly対応はGoチームではなく、ボランティアによって設計・実装された。したがって、スケジュールはボランティアの都合に左右される
  • Go 1.24以前でも、Go関数をJSにエクスポートすることは可能ではなかったか、よく覚えていない。以前、JSからエクスポートされたGo関数を問題なく呼び出せた記憶がある

    • 新しいWASI機能が以前と比べてどう改善されたのか説明してもらえると助かる(FFIを通じてより多くの型をサポートすること以外で)
    • 2つ目の質問。ポインタを整数にキャストして、WASMモジュールのインスタンスメモリから文字列や複雑な型を取り出すことができた。Goにおける自分の型のバイナリ表現が安定していると保証されるなら、goos=wasip1 を使って生成したWASMモジュールにポインタを渡すこの方法が、今でも有効なのか気になる
  • mainパッケージで大文字で始まるすべての関数をエクスポートするほうが、より「Goらしい」と思う。エクスポートは通常言語の仕組みとして機能するので、小文字で始まるものを明示的に指定するときだけコンパイラディレクティブを使うのがよい

    • これは既存の cgo のエクスポート方式と同じだ。以前の例にならっている。使い勝手は依然として言語の外側にある
  • WASMコンポーネントモデルとの連携についての言及がない

  • GoとWASMのガベージコレクションがどう動作するのか気になる

  • 強い型付けと優れたWASMサポートを備えた低レベル言語があればよいのに

  • ホストプログラムで実行中のWASMモジュールをどうデバッグするのか気になる

  • より多くのWASM機能を求める動きが、若いエコシステムに取り返しのつかない害を与えるのではないかと心配している。GoがWASMに追加した機能の大半は、コンポーネントモデルの提案がすでにマージされていればネイティブに実現できたはずだ

    • 標準はゆっくり進化しており、採用が進むにつれて、WASIのような非標準機能を永続的にサポートしなければならなくなる危険がある