# Echo vs Gin vs net/http 徹底比較：Go の Web フレームワーク選定と移行の意思決定ガイド

> Go の Web フレームワーク選定を意思決定するための比較ガイド。Echo（v5）と Gin（v1.12）、標準 net/http、Fiber を、ハンドラ署名・エラー処理・ミドルウェア・バインディング・性能・エコシステムの軸で公平に比較し、用途別の選定フレームワークと Gin↔Echo の移行方針までを実コードで解説します。

- 公開日: 2026-06-28
- 著者: 友田 陽大
- タグ: Go, Echo, アーキテクチャ設計, 技術選定, パフォーマンス
- URL: https://tomodahinata.com/blog/go-echo-vs-gin-framework-comparison-selection-migration-guide
- カテゴリ: Go・Echo 本番運用
- 総合ガイド: https://tomodahinata.com/blog/go-echo-framework-production-guide

## 要点

- 性能は決め手にならない。Echo・Gin はどちらも radix-tree ルーターでゼロアロケーション級。実アプリのボトルネックは DB と I/O であってルーターではない
- 決定的な違いはエラー処理。Echo は handler が error を返し集中ハンドラへ。Gin は c.JSON で都度書く（中央集権の標準がない）
- Gin はコミュニティと三者ミドルウェアが最大。Echo は内蔵ミドルウェアが充実しAPIが一貫。成熟度なら Gin、一貫性なら Echo
- 依存を増やしたくない・小規模なら Go 1.22+ の強化された net/http だけで足りることも多い。Fiber は fasthttp 非互換が代償
- 選定は『チームの慣れ・エラー処理の好み・既存資産』で決める。移行は両者とも net/http 互換なので段階的に可能

---

「Go で API を作る。Echo と Gin、どっち？」——Go を始めると必ずぶつかる問いです。ネット上の比較記事の多くは**ベンチマークの数字**で勝敗を付けますが、それは実務ではほぼ意味がありません。**実アプリのボトルネックはルーターではなく DB と外部 I/O**だからです。

この記事は、[Go Echo 本番運用ガイド](/blog/go-echo-framework-production-guide)の選定編です。性能以外の**本当に効く違い**——エラー処理の思想、ミドルウェアの一貫性、エコシステムの成熟度——を公平に比較し、「あなたのプロジェクトでどれを選ぶべきか」を**軸**で答えます。Echo に肩入れせず、Gin が向く場面も明記します。

> **この記事のルール**：各フレームワークの事実は **公式ドキュメント / リポジトリ（2026年6月時点。Echo v5・Gin v1.12 系）** に基づきます。バージョンは進むため、採用前に各公式で最新を確認してください。

---

## 1. まず性能の話を片付ける：ここは決め手にならない

率直に言います。**Echo と Gin の性能差は、実アプリでは観測できません。**

- Echo・Gin はともに **radix-tree（基数木）ベースのルーター**で、パラメータ付きルートでも**ゼロアロケーション級**。GitHub API 相当の全ルートを**約10マイクロ秒**で解決します。
- この差（数マイクロ秒）は、1回の DB クエリ（**数ミリ秒**＝1000倍以上）や外部 API 呼び出しに完全に埋もれます。

つまり「どちらが速いか」でフレームワークを選ぶのは、**家を選ぶのに玄関マットの厚さで決める**ようなものです。性能が本当に最優先なら検討対象は Fiber（`fasthttp`）ですが、それには[後述の大きな代償](#5-fiber-と-net-http-という選択肢)があります。**性能はこの比較から外し**、設計と運用の軸で見ます。

---

## 2. 最大の違い：エラー処理の思想

ここが Echo と Gin を分ける、最も実務的な差です。

### Echo：handler が `error` を返し、集中ハンドラで一元処理

```go
// Echo：エラーは return するだけ。変換は集中 HTTPErrorHandler に集約
func getUser(c *echo.Context) error {
	user, err := repo.Find(c.Request().Context(), c.Param("id"))
	if err != nil {
		return err // ← 1箇所の HTTPErrorHandler が HTTP に変換・ログ・通知
	}
	return c.JSON(http.StatusOK, user)
}
```

### Gin：handler は `error` を返さず、その場でレスポンスを書く

```go
// Gin：各ハンドラで c.JSON / c.AbortWithStatusJSON を書く（中央集権の標準なし）
func getUser(c *gin.Context) {
	user, err := repo.Find(c.Request.Context(), c.Param("id"))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) // 都度
		return
	}
	c.JSON(http.StatusOK, user)
}
```

Gin にも `c.Error()` でエラーを蓄積する仕組みはありますが、**「return すれば集中ハンドラが整形する」という Echo の規約のような標準形が無く**、エラー処理が各ハンドラに散らばりがちです。**エラー処理・ログ・機微情報の遮断を一箇所に集約したい**なら Echo、**素朴に都度書く**のが好みなら Gin。これは優劣ではなく**思想の違い**で、[集中エラー設計](/blog/go-echo-request-binding-validation-error-handling-guide#5-エラーハンドリング握りつぶさずreturnし一箇所で整形する)を重視する私は Echo を好みます。

---

## 3. 各軸の比較表

| 軸 | **Echo v5** | **Gin v1.12** | 標準 **net/http**（Go 1.22+） |
| --- | --- | --- | --- |
| 基盤 | `net/http` | `net/http` | — |
| ルーター | radix tree（静→param→*） | radix tree（httprouter 系） | パターンマッチ（メソッド対応） |
| ハンドラ署名 | `func(c *echo.Context) error` | `func(c *gin.Context)` | `func(w, r)` |
| エラー処理 | **集中 HTTPErrorHandler** | 各所で `c.JSON`／`c.Error` | 自前 |
| ミドルウェア | 内蔵が充実・API 一貫 | 内蔵 + **三者が最多** | 自前（`http.Handler`） |
| バインド/検証 | `c.Bind`+`Validator` 差込 | `ShouldBindJSON`+validator 内蔵 | 自前 |
| ロギング | **log/slog 標準**（v5） | 独自 + 三者 | 自前 |
| 成熟度・事例 | 多い | **最多（スター・採用数）** | 標準＝無限 |
| 学習コスト | 低〜中 | 低 | 中（手書き多い） |

ざっくり言うと——**Gin は「最も成熟・最大エコシステム」、Echo は「APIが一貫・内蔵が充実・v5 で近代化（slog/ジェネリクス/StartConfig）」、net/http は「依存ゼロ」**。

---

## 4. ミドルウェアとエコシステム：Gin の強み

公平に書きます。**サードパーティ・ミドルウェアの数と情報量は Gin が最大**です。CORS・レート制限・キャッシュ・認証など、よくある課題の「枯れた解」が見つかりやすく、採用事例も最多。チームに Gin 経験者が多いなら、その**慣れ**は性能差より遥かに価値があります。

一方 Echo は、CORS・CSRF・Secure・RateLimiter・RequestLogger などを**フレームワーク内蔵**で持ち、設定構造体（`XxxWithConfig`）の作法が**全ミドルウェアで一貫**しています。三者依存を増やさずに本番要件を満たしやすいのが Echo の強みです（[ミドルウェア完全ガイド](/blog/go-echo-middleware-cors-csrf-jwt-rate-limit-security-guide)）。

> 判断軸：**「枯れた三者解と最大の事例」**が欲しいなら Gin。**「内蔵で一貫、依存を絞る」**なら Echo。

---

## 5. Fiber と net/http という選択肢

- **Fiber**：`fasthttp` 上に作られ、生のスループットは最速級。ただし**`net/http` 非互換**——`context.Context` の流儀や `http.Handler` 資産、標準ミドルウェアがそのまま使えません。Go の標準エコシステムから外れる代償は、長期保守では重くのしかかります。**極限の生スループットが要件**で、その代償を受け入れられる場合のみ。
- **標準 net/http（Go 1.22+）**：強化された `ServeMux` が**メソッド付きパターン**（`GET /users/{id}`）に対応し、小〜中規模なら**フレームワークなしで十分**になりました。依存を増やしたくない・ライブラリの寿命に縛られたくないなら、まず標準で組めないか検討する価値があります。

```go
// Go 1.22+ の標準 net/http（依存ゼロ）
mux := http.NewServeMux()
mux.HandleFunc("GET /users/{id}", func(w http.ResponseWriter, r *http.Request) {
	id := r.PathValue("id")
	// ...
})
```

ただし、エラー集約・バインド・検証・豊富なミドルウェアを**自前で書く**コストは残ります。それが増えてきたら Echo/Gin の出番です。

---

## 6. 移行：Gin ↔ Echo は段階的にできる

「Gin で始めたが Echo に寄せたい（逆も）」は現実的に可能です。**両者とも `net/http` 互換**なので、`http.Handler` 境界で**共存**させながら段階移行できます。

移行時に書き換わる主なポイント：

| 項目 | Gin | Echo v5 |
| --- | --- | --- |
| ハンドラ | `func(c *gin.Context)` | `func(c *echo.Context) error` |
| ルート | `r.GET("/u/:id", h)` | `e.GET("/u/:id", h)` |
| パラメータ | `c.Param("id")` | `c.Param("id")` |
| JSON 応答 | `c.JSON(200, obj)` | `return c.JSON(200, obj)` |
| バインド | `c.ShouldBindJSON(&x)` | `c.Bind(&x)` |
| エラー | 各所で `c.JSON` | `return err`（集中ハンドラ） |
| グループ | `r.Group("/api")` | `e.Group("/api")` |

最大の作業は**「都度レスポンスを書く Gin 流」から「error を return する Echo 流」への発想転換**です。逆方向（Echo→Gin）では、集中エラーハンドラの責務を各ハンドラ or 共通ミドルウェアに散らす必要があります。いずれも[クリーンアーキテクチャ](/blog/go-echo-clean-architecture-dependency-injection-google-wire-guide)で Controller を薄く保っていれば、影響範囲は Controller 層に局所化できます——これが層分割の実利です。

---

## 7. 選定フレームワーク：あなたはどれを選ぶべきか

```text
依存をほぼ増やしたくない / 小〜中規模 / ライブラリ寿命に縛られたくない
  └─→ 標準 net/http（Go 1.22+）。足りなくなったら Echo/Gin へ

最大の事例・三者ミドルウェア・チームが Gin 慣れ
  └─→ Gin

集中エラー処理 / 内蔵ミドルウェアの一貫性 / 依存を絞る / v5 の近代化(slog)
  └─→ Echo

生スループットが最優先 & net/http 非互換を許容できる
  └─→ Fiber（少数派の選択。代償を理解した上で）
```

**正直な結論**：REST/JSON の業務 API を**本番品質で素早く**作るなら、Echo と Gin はどちらも正解です。**性能で迷う必要はありません**。決め手は「エラー処理の思想（集中 vs 都度）」「チームの慣れ」「既存資産」。私自身は、集中エラー処理と内蔵ミドルウェアの一貫性、v5 での近代化を評価して [Echo を採用](/case-studies/restaurant-matching)していますが、これは思想の選択です。

---

## まとめ：フレームワーク選定の7原則

1. **性能で選ばない**。Echo/Gin の差は実アプリで観測不能。ボトルネックは DB と I/O。
2. **最大の違いはエラー処理**。集中（Echo）か都度（Gin）か、思想で選ぶ。
3. **エコシステム最大は Gin**、内蔵の一貫性は Echo。
4. **依存を絞るなら Go 1.22+ の net/http** をまず検討。
5. **Fiber は net/http 非互換が代償**。生スループット最優先のときだけ。
6. **チームの慣れ・既存資産**は性能差より重い判断材料。
7. **移行は両者 net/http 互換で段階的に可能**。Controller を薄く保てば影響は局所化。

技術選定に「唯一の正解」はありません。あるのは「**あなたの制約に対する最適解**」です。選定やアーキテクチャの相談は、[B2B SaaS のアーキテクチャ設計](/blog/award-winning-b2b-saas-architecture-deep-dive)や[レガシー産業の技術選定フレームワーク](/blog/legacy-industry-dx-technology-selection-framework)の考え方も合わせてどうぞ。Echo を選んだ後の作り込みは[本番運用ガイド](/blog/go-echo-framework-production-guide)へ。
