WsamとWASIにGoで触れてみる

## はじめに

Wasm（WebAssembly）は、ブラウザだけでなくサーバーや組み込み環境でも実行可能な バイナリフォーマットのことを指します。  
一方で、WASI（WebAssembly System Interface）は、Wasmをより汎用的な環境で動作させるためのAPI規格のことであり、Webブラウザに限定されないアプリケーションの開発を可能にします。

今回は、WasmとWASIの基礎概念を学び、Goを用いてWebAssemblyモジュールを作成する方法を解説してみようと思います。
ここ最近新し目の概念や技術に触れることが多くて、インプットもアウトプットも大変だ〜頑張ろう

**対象読者**
- Wasm（WebAssembly）とWASIの基本を学びたい方
- GoでWebAssemblyを活用する方法を知りたい方
- WASIを使ってWebAssemblyをブラウザ以外の環境で実行してみたい方

**目次**
1. Wasm（WebAssembly）とは？
   - Wasmの概要と仕組み
   - なぜWasmを使うのか？
2. WASI（WebAssembly System Interface）とは？
   - WASIの役割と特徴
   - WasmとWASIの違い
3. GoでWasmを作成する
   - GoでWasmモジュールをコンパイル
   - ブラウザでWasmを実行する方法
4. GoでWASIを活用する
   - WASIを使ったファイルI/Oの実装
   - `wasmtime`でGoのWasmモジュールを実行
5. まとめ

---

## 1. Wasm（WebAssembly）とは？

#### **1.1 Wasmの概要と仕組み**

Wasm（WebAssembly）は、ブラウザで高パフォーマンスなコードを実行するためのバイナリフォーマットのことです。

| 特徴 | 説明 |
|------|------|
| **高速** | ほぼネイティブ並みのパフォーマンスを実現 |
| **クロスプラットフォーム** | ブラウザ・サーバー・組み込み環境で実行可能 |
| **セキュア** | サンドボックス内で動作し、安全性が高い |

#### **1.2 なぜWasmを使うのか？**

Wasmを利用することで、GoやRustなどの言語で書かれたコードを、JavaScriptの代わりにWebで実行することができます。

例えば、以下のようなユースケースがあります。
- 計算量の多い処理（画像処理・データ解析）
- ゲームエンジンや3Dレンダリング
- WebブラウザでのGoアプリケーション実行

---

## 2. WASI（WebAssembly System Interface）とは？

#### **2.1 WASIの役割と特徴**

WASI（WebAssembly System Interface）は、WebAssemblyをブラウザ以外の環境で動作させるための API仕様です。

| 機能 | 説明 |
|------|------|
| **ファイル I/O** | ファイルの読み書きが可能 |
| **ネットワーク** | ソケット通信やHTTPリクエストのサポート |
| **環境変数** | システムの環境変数へアクセス可能 |

#### **2.2 WasmとWASIの違い**

| 項目 | Wasm | WASI |
|------|------|------|
| **対象環境** | ブラウザ中心 | サーバー、CLI、組み込み環境 |
| **システムAPI** | JavaScript経由でアクセス | 直接システムリソースにアクセス |
| **用途** | フロントエンド開発向け | バックエンドやCLIアプリ向け |

---

## 3. GoでWasmを作成する

#### **3.1 GoでWasmモジュールをコンパイル**

Goでは`GOOS=js`と`GOARCH=wasm`を指定することでWasmにコンパイルできます。

**wasm_program.go**
```go
package main

import "syscall/js"

func add(this js.Value, args []js.Value) interface{} {
    return js.ValueOf(args[0].Int() + args[1].Int())
}

func main() {
    js.Global().Set("add", js.FuncOf(add))
    select {}
}
```

**コンパイル**
```sh
GOOS=js GOARCH=wasm go build -o main.wasm wasm_program.go
```

#### **3.2 ブラウザでWasmを実行する方法**

```html
<!DOCTYPE html>
<html>
<head>
    <script>
        WebAssembly.instantiateStreaming(fetch("main.wasm"), {}).then(obj => {
            console.log("2 + 3 =", obj.instance.exports.add(2, 3));
        });
    </script>
</head>
<body>
    <h1>Wasm + Go</h1>
</body>
</html>
```

---

## 4. GoでWASIを活用する

#### **4.1 WASIを使ったファイルI/Oの実装**

**wasi_program.go**
```go
package main

import (
    "fmt"
    "io/ioutil"
    "os"
)

func main() {
    data, _ := ioutil.ReadFile("input.txt")
    fmt.Println("File content:", string(data))
}
```

**WASIに対応したコンパイル**
```sh
GOOS=wasip1 GOARCH=wasm go build -o main.wasm wasi_program.go
```

#### **4.2 `wasmtime`でGoのWasmモジュールを実行**

**`wasmtime`をインストール**
```sh
brew install wasmtime
```

**実行**
```sh
wasmtime main.wasm --dir=.
```

---

## 5. まとめ

| 項目 | 説明 |
|------|------|
| **Wasm（WebAssembly）** | 高速・安全なコードをWebで実行するための技術 |
| **WASI（WebAssembly System Interface）** | Wasmをブラウザ外で実行するための API |
| **GoでのWasm実装** | `syscall/js`を使ってJavaScriptと連携 |
| **GoでのWASI実装** | ファイルI/OやシステムAPIを活用可能 |


次は、Wasmでのリアルタイムデータ処理についてや、WASI を活用したサーバーレス実行環境の構築についても書いてみようと思います！
日々の学習頑張ります〜