---
title: "TinyGoとは？通常のGoとの違い・小さくなる仕組み・Lチカ・Wasmを0.43.0で実測"
url: "https://www.issoh.co.jp/tech/details/10217/"
published: 2025-12-11
updated: 2026-10-23
categories: ["Go"]
publisher: "株式会社一創"
---

# TinyGoとは？通常のGoとの違い・小さくなる仕組み・Lチカ・Wasmを0.43.0で実測

TinyGoは、Go言語のソースコードをマイコンやWebAssembly（Wasm）向けの小さなバイナリにコンパイルする、LLVMベースの別実装コンパイラです。同じ「Hello World」を通常のGoでビルドすると約2.5MB、TinyGo 0.43.0では約240KBでした。2026年10月9日公開の0.43.0で、サイズ差と小さくなる仕組み、インストール、PicoとESP32のLチカ、Wasmのターゲットを実測しました。

## まとめ：TinyGoの要点と向いている場面

- TinyGoはGo公式コンパイラ（gc）とは別のコンパイラで、コード生成にLLVM 22を使います。現行版は0.43.0（2026年10月9日）で、組み合わせるGoツールチェーンは1.25〜1.27です。
- fmtでHello Worldを出すプログラムは、通常のGoで2,504,528バイト、TinyGoで239,936バイトでした（約10分の1）。WASI向けは2,479,945バイトに対して179,256バイトです。
- 小さくなる理由は、全体を1回でコンパイルして不要なコードを落とすこと、初期化をコンパイル時に済ませること、GCとスケジューラを選べることです。Wasmでは`-scheduler=none`だけで179,256バイトが27,030バイトに減りました。
- 0.43.0からWasmでもpanicを`recover()`で回復できます。公式の言語サポートページはまだ「WebAssemblyでは不可」のままです。
- Raspberry Pi Pico向けのLチカはflash 11,700バイトです。encoding/jsonを入れると、Go 1.27では347,820バイトに膨らみ、XIAO（SAMD21）のflashには収まりませんでした。Wasmのビルドにはbinaryenの`wasm-opt`が別途必要です。

## TinyGoの定義と現行版0.43.0の位置づけ

開発元はGitHubの[tinygo-org/tinygo](https://github.com/tinygo-org/tinygo)で、リポジトリの説明は「Go compiler for small places」です。Go本体とは別のプロジェクトで、型チェックと標準ライブラリはインストール済みのGoのものを使い、コード生成と最適化をLLVMに任せます。そのためGo本体が先に必要です。Go本体の導入から始める場合は[Go言語とは｜1.27系の導入からHTTP APIを動かすまでの実装入門](/tech/details/17483/)を先に済ませてください。

対応するGoの版はソースコードに定数で書かれています。0.43.0の[builder/config.go](https://github.com/tinygo-org/tinygo/blob/v0.43.0/builder/config.go)は`minorMin = 25`、`minorMax = 27`で、範囲外のGoでは「requires go version 1.25 through 1.27」というエラーで止まります。公式サイトのインストール手順は「Go v1.23 or above」のままなので、Go 1.23や1.24の環境では手順どおりに入れても動きません。

| 版      | 公開日（UTC）   | 主な変更                                    |
| ------ | ---------- | --------------------------------------- |
| 0.43.0 | 2026-10-09 | Wasm・Xtensaでのrecover、-trimpath、ESP32-H2 |
| 0.42.0 | 2026-09-01 | Go 1.27・LLVM 22対応、ランタイムpanicのrecover    |
| 0.41.1 | 2026-04-22 | 0.41.0の修正版                              |
| 0.41.0 | 2026-04-21 | 前回のマイナー版                                |

[0.43.0のリリースノート](https://github.com/tinygo-org/tinygo/releases/tag/v0.43.0)はGoとの互換性に重点を置いた版だと説明しており、synctest、reflectのNewAtとSlice3、ESP32とnRF52のI2Sなどが入りました。再現可能なビルド用の`-trimpath`も追加され、wasip1向けに2回ビルドした出力のSHA-1は一致しました。版番号はまだ0.x系で、互換性を約束する1.0には達していません。

## 通常のGo（gc）とのバイナリサイズの差

`fmt.Println("hello, tinygo")`だけのmain関数を、`go build`と`tinygo build`（Wasmは`-target=wasip1`など）でビルドし、出力ファイルのバイト数を比べました。環境はmacOS 26.6（Intel）、Go 1.27.2、TinyGo 0.43.0、測定日は2026年10月23日です。TinyGoのWasm出力には`-no-debug`を付けています。

| ビルド対象                     | 通常のGo（バイト） | TinyGo（バイト） |
| ------------------------- | ---------- | ----------- |
| macOSネイティブ（fmt.Println）   | 2,504,528  | 239,936     |
| 同上（Goは-s -w付き）            | 1,628,544  | 239,936     |
| WASI（wasip1・fmt.Println）  | 2,479,945  | 179,256     |
| ブラウザ（js/wasm・fmt.Println） | 2,506,776  | 159,433     |
| WASI（組み込みのprintln）        | 1,910,065  | 24,262      |

fmtをやめて組み込みの`println`にすると、TinyGoのwasip1出力は179,256バイトから24,262バイトに縮みます。通常のGoは1,910,065バイトで、大きくは減りません。`-no-debug`を外すとwasip1は650,268バイトになるので、配布するWasmには付けます。

サイズはTinyGoの版だけでなく、組み合わせるGoの版でも動きます。同じGo 1.27.2で0.42.0に戻すと、wasip1のHello Worldは98,016バイト、ネイティブは218,808バイトでした。0.43.0ではそれぞれ179,256バイトと239,936バイトに増えています。原因までは切り分けていませんが、0.43.0にはAsyncifyを使ってpanicを回復する実装が入っています。サイズを詰めているなら、版を上げる前後で出力を比べてください。

## TinyGoが小さくなる仕組み：全体コンパイル・初期化・ランタイムの選択

TinyGoのバイナリが小さい理由は、公式ドキュメントの[コンパイルの流れ（Pipeline）](https://tinygo.org/docs/concepts/compiler-internals/pipeline/)と[Goとの違い](https://tinygo.org/docs/concepts/compiler-internals/differences-from-go/)に書かれています。大きく分けて次の3つです。

### プログラム全体の一括コンパイルと不要コードの削除

TinyGoはプログラム全体を、途中のリンクを挟まず1回でコンパイルします。大きなプログラムではビルドが遅くなる代わりに、最適化の余地が広がると公式は説明しています。GoのSSAをLLVM IRに落とし、LLVMの最適化とTinyGo独自のエスケープ解析などをかけます。全体が見えているので、どこからも呼ばれない関数や使われないグローバル変数を丸ごと落とせます。

### パッケージ初期化のコンパイル時評価

通常のGoのコンパイラも、定数だけで決まる初期値は静的データとして置きますが（[staticinit](https://go.dev/src/cmd/compile/internal/staticinit/sched.go)）、関数呼び出しを含む初期化は実行時のinit処理に残ります。TinyGoはこうした初期化関数も、コンパイル時にできるところまで解釈して実行します。初期化の命令列の代わりに初期値のデータだけをflashに置けばよく、定数とわかったグローバル変数はRAMではなくflashに置かれます。

### GC・スケジューラ・panic処理の設定別サイズ比較

3つめはランタイムの選択です。[公式の最適化ガイド](https://tinygo.org/docs/guides/optimizing-binaries/)が挙げるオプションを、fmtのHello World（wasip1）とPicoのLチカで1つずつ試しました。既定の最適化は`-opt=z`（サイズ優先）です。

| オプション            | wasip1（バイト） | Pico flash（バイト） |
| ---------------- | ----------- | --------------- |
| 既定               | 179,256     | 11,700          |
| \-opt=s          | 184,450     | 12,304          |
| \-opt=2          | 258,207     | 24,608          |
| \-gc=leaking     | 151,278     | 10,596          |
| \-panic=trap     | 115,834     | 10,116          |
| \-scheduler=none | 27,030      | 10,424          |
| 上の3つを併用          | 11,511      | 8,320           |

Wasmで効くのは`-scheduler=none`です。wasip1の既定のスケジューラは`asyncify`で、goroutineの切り替えのために関数を書き換えるAsyncifyがバイナリ全体を膨らませます。これを外すと85%減りました。一方Picoでは、ランタイムを削る3つのオプションの効果は1.1〜1.6KBずつ、併用でも3,380バイトです。速度優先の`-opt=2`は逆に2倍以上の24,608バイトになりました。`-gc=none`はPicoのLチカでも「object allocated on the heap with -gc=none」でビルドに失敗し、ランタイムと`errors`パッケージのヒープ確保が原因として表示されました。

どのオプションにも代償があります。`-scheduler=none`は`go`文が使えなくなり、Wasmではpanicの回復もできなくなります（次章）。`-panic=trap`はpanicのメッセージを出さずに止まり、`-gc=leaking`は確保したメモリを一切解放しません。3つの併用（Hello Worldで11,511バイト）が向くのは、呼び出しごとにインスタンスを作り直すか、ヒープ確保をしない計算関数をWasmで公開する場合です。同じインスタンスで確保を繰り返すとメモリが枯渇するので、常駐するマイコンのプログラムでは既定のまま使います。

### ターゲット別のGCとスケジューラの既定値

既定のGCとスケジューラはターゲットで違い、`tinygo info -target=<ターゲット名>`で確認できます。0.43.0の値は次のとおりです。

| ターゲット                | GC           | スケジューラ   |
| -------------------- | ------------ | -------- |
| pico・esp32c3-generic | conservative | tasks    |
| arduino（AVR）         | conservative | none     |
| wasip1               | precise      | asyncify |
| wasm-unknown         | leaking      | none     |

通常のGoのgoroutineはM:Nスケジューリングで複数スレッドに載りますが（仕組みは[ゴルーチン（Goroutine）とは？Go言語の並行処理を支える軽量スレッドの仕組みと使い方](/tech/details/4632/)）、TinyGoの`tasks`は単一コア上の協調的な切り替えです。メインループでのヒープ確保を避けたい場合は、`-print-allocs=.`を付けてビルドすると、ヒープに逃げた箇所がファイル名と行番号で表示されます。

## recover・reflect・encoding/jsonの対応状況

[公式の言語サポートページ](https://tinygo.org/docs/reference/lang-support/)は冒頭に「as of june 2023」とあり、recoverは「WebAssemblyを除く大半のアーキテクチャで対応」「ランタイムpanicは回復できない」と書かれています。0.43.0ではどちらも当てはまりません。ゼロ除算とnil mapへの書き込みを`recover()`で受けるコードを試すと、macOSネイティブでも、wasip1でビルドしてNode.js 26.5.0のWASIで動かした場合でも、両方とも回復しました。0.42.0ではwasip1の同じコードがpanicで止まっていました。ただし`-scheduler=none`を付けたwasip1では回復できず、「panic: runtime error: integer divide by zero」で止まりました。Wasmでrecoverを使うなら、前章の`-scheduler=none`による縮小とは両立しません。

reflectは再実装されていて大半は動きますが、一部は未対応です。cgoの`#cgo`行も部分対応にとどまります。既存のGoライブラリを使うなら、対象ターゲットで実際にビルドして動くかを確かめてから採用します。

encoding/jsonは0.43.0でMarshalとUnmarshalとも正しく動きましたが、サイズは大きくなります。構造体1つを変換するだけのプログラムをPico向けにビルドするとflashは347,820バイト、静的RAMは30,572バイトで、Lチカの約30倍です。flash 256KBのXIAO（SAMD21）向けは「flash overflowed by 91588 bytes」でビルドできませんでした。10月3日に0.42.0とGo 1.26.5で測ったときは148,432バイトで、0.42.0のままGoを1.27.2にすると342,620バイトでした。増えた分はGo 1.27の標準ライブラリ側から来ているので、flashの小さいボードではGoの版を上げる前にサイズを確かめてください。

## インストール手順：macOS・Windows・Linux

どのOSでも先にGo 1.25〜1.27を入れます。Wasmを出力するにはbinaryenの`wasm-opt`が必要で、0.43.0のmacOS用tarballを展開しただけの状態では、wasip1のビルドが「error: could not find wasm-opt, set the WASMOPT environment variable to override」で止まりました。binaryen（2026年10月時点の最新はversion\_133）を入れてPATHを通すと解消します。

### macOSでの導入

Homebrewの専用tapから入れます。tapは2026年10月23日時点で0.43.0を指しています。Homebrew 6.0.0からは公式以外のtapに[明示的な信頼](https://docs.brew.sh/Tap-Trust)が必要になり、`brew tap`のあとに短い名前で`brew install tinygo`とすると止まります。完全修飾名で指定すれば、そのformulaだけを信頼して入れられます。

```
brew install tinygo-org/tools/tinygo
brew install binaryen
tinygo version
```

Intel Macでは「tinygo version 0.43.0 darwin/amd64 (using go version go1.27.2 and LLVM version 22.1.4)」と表示されました。tarballで入れる場合は`tinygo0.43.0.darwin-amd64.tar.gz`（Intel）か`darwin-arm64`（Apple Silicon）を展開し、`tinygo/bin`をPATHに追加します。

### Windowsでの導入

公式はScoopでの導入を案内しています。Scoopを使わない場合は`tinygo0.43.0.windows-amd64.zip`を展開し、`bin`フォルダをユーザー環境変数のPATHに追加します。

```
scoop install go
scoop install tinygo
scoop install binaryen
```

### Linux（Ubuntu・Debian）での導入

amd64・arm64・armhf向けの.debが[GitHub Releases](https://github.com/tinygo-org/tinygo/releases)で配布されています。

```
wget https://github.com/tinygo-org/tinygo/releases/download/v0.43.0/tinygo_0.43.0_amd64.deb
sudo dpkg -i tinygo_0.43.0_amd64.deb
sudo apt install binaryen
```

実機への書き込みに使うツールはボードのターゲット定義で決まります。Arduino UnoなどAVRマイコンは`avrdude`、Arduino Nano 33 IoTは`bossac`が必要です。PicoやXIAOのように書き込み方式が`msd`（USBマスストレージ）のボードは追加のツールが要りません。

## ハードウェアなしで試す：TinyGo Playground

ボードが手元に無い段階では、公式の[TinyGo Playground](https://play.tinygo.org/)で試せます。コードはサーバーで実行するのではなくWasmにコンパイルしてブラウザで動かし、いくつかのボードをブラウザ上でシミュレーションします。[ソースコード](https://github.com/tinygo-org/playground)のボード定義には、Raspberry Pi Pico、Arduino Uno、Arduino Nano 33 IoT、BBC micro:bit v1、Seeed Studio XIAO ESP32-S3、Gopher Badgeなどが並んでいます。公式は「シミュレーションは実機の挙動と異なる場合がある」と注意しており、ドラッグ＆ドロップで書き込めるボードならFlashボタンからそのまま実機へ書き込めます。

## マイコンでLチカ：Raspberry Pi PicoとESP32

TinyGo 0.43.0の`tinygo targets`は199件のターゲット名を返しました。ボード上のLEDを0.5秒ごとに点滅させるコードは次のとおりです。

```
package main

import (
	"machine"
	"time"
)

func main() {
	led := machine.LED
	led.Configure(machine.PinConfig{Mode: machine.PinOutput})
	for {
		led.High()
		time.Sleep(500 * time.Millisecond)
		led.Low()
		time.Sleep(500 * time.Millisecond)
	}
}
```

`go mod init blink`でモジュールを作り、ボードを接続して書き込みます。`-size short`を付けると、ビルド時に集計したflash（code+rodata+data）と静的RAM（data+bss）が表示されます。実行時のヒープとスタックは含みません。

```
tinygo flash -target=pico .
tinygo build -target=pico -size short -o blink.uf2 .
```

Picoの書き込み方式は`msd`で、`RPI-RP2`という名前のドライブにUF2ファイルをコピーします。初回はBOOTSELボタンを押しながらUSBを挿します。2回目以降はTinyGoがボードをブートローダーへ再起動させます。Pico Wとの違いは[Raspberry Pi Pico Wとは？WH・Pico 2 Wとの違い、できることとWi-Fi接続【2026年10月】](/tech/details/11676/)で整理しています。

主要ボード向けのビルド結果です（単位はバイト・実機での点滅は未確認）。

| ターゲット            | flash  | 静的RAM |
| ---------------- | ------ | ----- |
| pico（RP2040）     | 11,700 | 6,188 |
| pico2（RP2350）    | 10,340 | 6,180 |
| xiao（SAMD21）     | 8,220  | 5,388 |
| arduino-nano33   | 8,236  | 5,388 |
| arduino（Uno・AVR） | 928    | 560   |

### machine.LEDが無いボードの書き方

microbitとESP32の汎用ターゲットでは、上のコードが「undefined: machine.LED」で失敗します。ボード定義にオンボードLEDの定数が無いためで、ピン番号を直接指定します。次はESP32-C3のGPIO8に抵抗経由で外付けLEDをつないだ想定で、main関数の中身を置き換える例です。

```
led := machine.GPIO8
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
for {
	led.Set(!led.Get())
	time.Sleep(500 * time.Millisecond)
}
```

ビルド結果のflashはesp32c3-genericが6,666バイト、esp32-genericが8,664バイト、esp32s3-genericが7,842バイトでした（実機での点滅は未確認）。ESP32-WROOM系ではGPIO6〜11がSPI flashの接続に使われているため、ピン番号を機種間で流用せず、ボードの回路図で空いているGPIOを選んでください。ESP32系の書き込み方式は`esp32flash`で、USBシリアル経由です。ESP32を積んだ完成品の仕様は[M5Stack Core2とは？バッテリー容量・電源管理とv1.1/v1.3の違い、できること【2026年10月】](/tech/details/4470/)が参考になります。

### センサーを読む：tinygo.org/x/driversのBME280

センサーや表示器のドライバは、別リポジトリの[tinygo-org/drivers](https://github.com/tinygo-org/drivers)にまとまっています。READMEには145種類以上のドライバを収録とあり、最新はv0.36.0（2026年9月1日）です。温湿度・気圧センサーBME280をI2Cで読む例は次のとおりで、`go get tinygo.org/x/drivers@v0.36.0`で取り込みます。

```
package main

import (
	"machine"
	"time"

	"tinygo.org/x/drivers/bme280"
)

func main() {
	machine.I2C0.Configure(machine.I2CConfig{})
	sensor := bme280.New(machine.I2C0)
	sensor.Configure()
	if !sensor.Connected() {
		println("BME280が見つかりません。配線とI2Cアドレスを確認してください")
		return
	}
	for {
		t, err := sensor.ReadTemperature()
		if err != nil {
			println("温度の読み取りに失敗:", err.Error())
			time.Sleep(2 * time.Second)
			continue
		}
		h, err := sensor.ReadHumidity()
		if err != nil {
			println("湿度の読み取りに失敗:", err.Error())
			time.Sleep(2 * time.Second)
			continue
		}
		println("temp(m°C):", t, "hum(0.01%):", h)
		time.Sleep(2 * time.Second)
	}
}
```

ピンを指定しない`I2CConfig{}`では、PicoのI2C0はSDAがGP4、SCLがGP5になります。`ReadTemperature`は1000分の1度、`ReadHumidity`は0.01%単位の整数を返すので、表示するときに割り算します。センサーが見つからないときは読み取りに進まず終了し、読み取りに失敗したときは値を表示せず2秒後に再試行します。このコードのPico向けビルドはflash 18,088バイト・静的RAM 6,248バイトでした（実機での読み取りは未確認）。

## WebAssemblyで使う：4つのターゲットの違い

Wasm向けのターゲットは実行先で選び分けます。WebAssembly自体の仕組みは[WebAssembly(Wasm)とは？JavaScript連携とMemory・Table操作の実装](/tech/details/4250/)を参照してください。

| \-target     | 実行先               | 追加で必要なもの               |
| ------------ | ----------------- | ---------------------- |
| wasm         | ブラウザ・Node.js      | TinyGo同梱のwasm\_exec.js |
| wasip1       | WASIランタイム         | なし                     |
| wasip2       | コンポーネントモデル対応ランタイム | wasm-tools             |
| wasm-unknown | ホスト関数を持たない環境      | なし                     |

`-target=wasm`の出力は、通常のGoが配る`wasm_exec.js`ではなく、TinyGo側の`$(tinygo env TINYGOROOT)/targets/wasm_exec.js`と組み合わせます。ファイルはTinyGoと同じ版のものを使います（[公式のWasmガイド](https://tinygo.org/docs/guides/webassembly/wasm/)）。wasip2はビルドの最後に`wasm-tools component embed`を呼ぶため、wasm-toolsが無い環境では「\`wasm-tools component embed\` failed」で失敗しました。WASIの仕様と各版の違いは[WASIとは｜WebAssemblyをブラウザ外で動かすシステムインターフェース【2026年版】](/tech/details/13251/)で解説しています。

### 関数を1つだけ公開する748バイトのWasm

計算処理だけをJavaScriptから呼びたい場合は、`wasm-unknown`と`//go:wasmexport`を組み合わせます。wasm-unknownはWASIやJavaScriptのホスト関数を前提にせず、GCは解放しない`leaking`、スケジューラは`none`なので、ランタイムがほとんど入りません。

```
package main

//go:wasmexport add
func add(a, b int32) int32 {
	return a + b
}

func main() {}
```

```
tinygo build -target=wasm-unknown -no-debug -o add.wasm .
```

出力は748バイトでした。次の内容を`run.cjs`として保存し、`node run.cjs`で実行すると5が表示されます。

```
const fs = require('node:fs');
(async () => {
  const { instance } = await WebAssembly.instantiate(fs.readFileSync('add.wasm'), {});
  instance.exports._initialize();
  console.log(instance.exports.add(2, 3));
})();
```

`_initialize()`を飛ばすと「RuntimeError: unreachable」で落ちます。公式ガイドの例は`//export`という旧来の書き方ですが、Go本体と同じ`//go:wasmexport`が使えます。Rustで同じことをする場合の手順とサイズの比較軸は[RustでWebAssemblyを実装する手順｜wasm-packでのWASM化と軽量化・配置先の選び方【2026年版】](/tech/details/15290/)にまとめています。

## TinyGoを選ぶ場面と避ける場面

TinyGoが最も効くのは、Goを書けるチームがRP2040・SAMD21・nRF52のようなCortex-Mマイコンで、センサー読み取りや表示、USB HIDといった制御を書く場面です。Lチカはflash 11.7KBに収まり、goroutine・channel・selectもそのまま使えます。マイコンとクラウドをつなぐ仕組みまで含めて検討するなら、弊社の[AI/IoTソリューション](/service/ai/iot/)でも構成の相談を受けています。Wasmでは、通常のGoで2.5MBになるモジュールを数十KB〜180KBに縮めたい場合に選びます。

避けるべきなのは次の3つの場面です。

- reflectに依存するライブラリを多数取り込むサーバー処理をWasmへ移植する場合。ビルドが通っても挙動が変わることがあり、encoding/jsonだけでもマイコンでは300KBを超えます。通常のGoのwasip1出力（2.5MB）で困らないなら、gcのまま使う方が安全です。
- 厳密な応答時間の保証が要る制御。TinyGoのスケジューラは協調的な切り替えで、GCも停止を伴います。割り込み応答の上限を保証したいなら、[RTOSとは？リアルタイムOSの仕組み・主要製品の比較と採用判断を実装者目線で解説](/tech/details/15829/)で扱うRTOSとC/C++の組み合わせを選びます。OSを載せるかどうかの線引きは[組み込みOSとは？3分類の境界とITRON系の位置づけ・選定判断を実装者向けに解説](/tech/details/16820/)が参考になります。
- ArduinoのC++ライブラリをそのまま使いたい場合。TinyGoに移るより[arduino-cliとは？インストールからコンパイル・書き込み・CI自動化まで実践ガイド](/tech/details/12383/)でビルドを自動化する方が早く済みます。

## 日本語で学べる場：TinyGo Keebと書籍

国内では、自作キーボードとTinyGoを組み合わせたコミュニティ[TinyGo Keeb](https://tinygo-keeb.org/)が活動しています。はんだ付けからTinyGoでのファームウェア作りまでを1日で行うハンズオン「TinyGo Keeb Tour」を2024年から全国で開いており、[connpassのグループ](https://tinygo-keeb.connpass.com/)によると、2026年10月10日に秋葉原でTinyGo Conference 2026 in JAPANを開催し、次回のTourは11月7日の福井県鯖江市です。書籍では高砂正哲『基礎から学ぶTinyGoの組込み開発』（シーアンドアール研究所、2022年11月）があります。刊行から約4年経つため、版に依存するコマンドはリリースノートと照らして読みます。

## よくある質問

### TinyGoとは何ですか？

GoのソースコードをマイコンやWebAssembly向けに小さくコンパイルする、LLVMベースの別実装コンパイラです。現行版は0.43.0（2026年10月9日公開）で、Go 1.25〜1.27のツールチェーンと組み合わせて使います。

### TinyGoのGitHubリポジトリはどこですか？

github.com/tinygo-org/tinygo です。リリースファイル（.deb、.zip、macOS用tarball）は同リポジトリのReleasesから入手でき、センサー等のドライバは別リポジトリのtinygo-org/drivers、公式ドキュメントはtinygo.orgにあります。

### TinyGoと通常のGoは何が違いますか？

プログラム全体をLLVMで一括コンパイルし、初期化をコンパイル時に済ませ、ランタイムを小さくしている点です。fmtのHello Worldは通常のGoで2,504,528バイト、TinyGoで239,936バイトでした。代わりにreflectやcgoは一部しか実装されていません。

### TinyGoはESP32で使えますか？

使えます。0.43.0にはesp32-generic、esp32c3-generic、esp32s3-genericなどのターゲットがあり、GPIOを指定したLチカは3種類ともビルドできました。汎用ターゲットにはmachine.LEDが無いため、ピン番号を直接指定します。0.43.0ではESP32のPWMとI2Sにも対応しました。

### TinyGoでWasmをビルドすると「could not find wasm-opt」と出るのはなぜですか？

binaryenの`wasm-opt`が見つからないためです。macOSは`brew install binaryen`、Windowsは`scoop install binaryen`、Ubuntuは`sudo apt install binaryen`で入れます。導入済みなのに出る場合はPATHを確認するか、環境変数`WASMOPT`にwasm-optのフルパスを指定します。

## 関連記事

- [Go言語とは｜1.27系の導入からHTTP APIを動かすまでの実装入門](/tech/details/17483/)
- [WASIとは｜WebAssemblyをブラウザ外で動かすシステムインターフェース【2026年版】](/tech/details/13251/)
- [Raspberry Pi Pico Wとは？WH・Pico 2 Wとの違い、できることとWi-Fi接続【2026年10月】](/tech/details/11676/)
- [RustでWebAssemblyを実装する手順｜wasm-packでのWASM化と軽量化・配置先の選び方【2026年版】](/tech/details/15290/)
- [RTOSとは？リアルタイムOSの仕組み・主要製品の比較と採用判断を実装者目線で解説](/tech/details/15829/)

---

出典: [TinyGoとは？通常のGoとの違い・小さくなる仕組み・Lチカ・Wasmを0.43.0で実測](<https://www.issoh.co.jp/tech/details/10217/>)（株式会社一創）
