はじめに
Go言語でWebアプリケーションを構築しようとしたとき、最初に悩むのが「どのフレームワークを選ぶか」という点です。
Goには標準ライブラリでもHTTPサーバは書けますが、ルーティングやミドルウェアの実装など、便利な機能を求めるならフレームワークの導入が効果的です。
本記事では、Go製フレームワークの中でも特に軽量で高速、そして学習コストも低いとされる「Echo」を使って、最小構成のWebサーバを立ち上げる方法を解説します。
以下のような流れで進めていきます。
- Echoを選ぶ理由
- Echoのインストールと初期設定
- 基本構造とルーティングの理解
- リクエスト処理とレスポンスの書き方
- ミドルウェアの使い方
GoとEchoを使って、「まずは動くものを作る」を目指して一緒に進めていきましょう。
次のセクションでは、Echoを選ぶ理由について簡単に整理します。
今回作成したコードは下記のリポジトリに載せています。
Go + Echoを選ぶ理由
Goには複数のWebフレームワークが存在します。たとえば、Gin、Fiber、Echo、Chiなどが代表的です。その中でEchoを選ぶ理由は、以下のような特徴にあります。
1. 圧倒的な高速性と軽量さ
Echoは非常に高速に動作することで知られています。独自のルーティングエンジンを持ち、必要最低限のオーバーヘッドで高パフォーマンスを実現します。
2. シンプルかつ直感的なAPI
エラーハンドリングやルーティング、ミドルウェアの導入が簡潔に記述できる設計になっており、初学者でも扱いやすいです。
また、公式ドキュメントが充実しており、導入から応用まで一貫した理解が進めやすいのも魅力です。
3. ミドルウェアや機能が標準で豊富
- ログ出力
- リカバリ(パニックハンドリング)
- CORS、Gzip、JWTなどのミドルウェア
これらがEcho標準で提供されているため、別途ライブラリを探して導入する手間がありません。
4. エコシステムとの親和性
Echoは net/http をベースに作られているため、他のGoライブラリやミドルウェアと併用しやすいです。
また、Goの標準的なコンテキストやエラーハンドリングと自然に統合される設計がされており、拡張もしやすくなっています。
Ginとの比較(学習コスト・機能・記法)
GoのWebフレームワークで最もよく比較されるのが Gin と Echo です。どちらも高速かつ人気のあるフレームワークですが、用途や好みによって向き・不向きがあります。ここでは主に「学習コスト」「機能」「記法」の3つの観点で違いを整理します。
学習コスト:Echoの方がやや明示的
Gin は抽象度が高く、構文がシンプルでコンパクトに書けるため、最初はとっつきやすいです。ただし、内部的な挙動が隠蔽されている部分も多く、拡張やデバッグでつまずくこともあります。
Echo は構成が明示的で、各コンポーネントが分かれているため、「フレームワークの流れを追いやすい」という利点があります。Goの標準ライブラリに近い記述スタイルでもあり、Goらしさを学びたい人には親和性が高いです。
機能比較:Echoの方が標準機能が豊富
項目 | Gin | Echo |
---|---|---|
ルーティング | 高速で柔軟 | 高速でミドルウェア連携が強力 |
ミドルウェア | 最低限(カスタム中心) | 標準で多数同梱(CORS、Gzipなど) |
バリデーション | バリデーションライブラリと統合可 | 独自のバリデーション組込み |
レスポンスAPI | JSON, HTML などを簡単に返せる | より多様な形式に対応 |
サーバ設定 | Gin独自の設定が多い | net/http に忠実で柔軟性あり |
どちらも優れた選択肢ですが、Echoはより「Goの書き方」に寄り添った設計がなされており、慣れてくると心地よく感じる人も多いです。次章では、実際にEchoをインストールし、プロジェクトを立ち上げていきます。
Echoのインストールと初期設定
Echoを使った開発を始めるには、Goの標準的なプロジェクト構成とEchoのインストールを行います。ここではシンプルなサーバーを立ち上げるところまでを確認します。
1. プロジェクトディレクトリの作成
mkdir go-echo-example
cd go-echo-example
go mod init go-echo-example
2. Echoのインストール
$ go get github.com/labstack/echo/v4
main.go
3. 最小構成の package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, Echo!")
})
e.Logger.Fatal(e.Start(":8080"))
}
4. サーバーの起動
go run main.go
ブラウザで http://localhost:8080 にアクセスすると、Hello, Echo! と表示されるはずです。
5. フォルダ構成(将来の拡張を考慮)
本シリーズでは、以下のような構成を基本とします。
go-echo-example/
├── go.mod
├── main.go
├── handler/ // HTTPハンドラー
├── service/ // ビジネスロジック層
├── repository/ // データアクセス層
└── model/ // ドメインモデル
このように初期段階からディレクトリを分けておくことで、アプリケーションが大きくなっても無理なくスケールさせることができます。
補足: Airの導入でホットリロードを実現する
開発中にコードを変更するたびに go run を手動で実行するのは面倒です。そこで、air を導入してホットリロードを可能にします。
以下のコマンドで air
をインストールします。
go install github.com/air-verse/air@latest
air
は .air.toml
という設定ファイルを利用できます。プロジェクトルートに以下の内容で作成します。
# .air.toml
root = "."
tmp_dir = "tmp"
[build]
cmd = "go build -o ./tmp/main ."
bin = "tmp/main"
include_ext = ["go"]
exclude_dir = ["tmp", "vendor"]
[log]
time = true
項目 | 意味 |
---|---|
root |
監視するディレクトリのルート |
tmp_dir |
ビルド成果物の置き場 |
[build] |
ビルドと実行の設定 |
cmd |
ビルドコマンド(ここではGoのバイナリを tmp/main にビルド) |
bin |
実行するバイナリファイルのパス |
include_ext |
監視するファイルの拡張子 |
exclude_dir |
監視対象から除外するディレクトリ |
以下のコマンドを実行すると、air がソースコードの変更を監視し、即座に再起動してくれます。
air
Echoの基本構造を理解する
Echoは、最小限のコードでWebアプリケーションを構築できることが特徴です。このセクションでは、Echoアプリの全体像と、どのようにしてリクエストを受け取り、レスポンスを返すのかを見ていきます。
基本的な構成
Echoを使ったアプリケーションの典型的な構成は以下のようになります。
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, Echo!")
})
e.Start(":8080")
}
各要素の解説
構成要素 | 説明 |
---|---|
echo.New() |
Echoインスタンスを生成します。ルーティングやミドルウェア設定に使われます。 |
e.GET(...) |
HTTPメソッドとパスに応じたルートハンドラを定義します。他に POST 、PUT 、DELETE なども使用可能です。 |
c echo.Context |
リクエストやレスポンスにアクセスするためのコンテキストです。Echoの特徴的なインターフェースです。 |
c.String(...) |
クライアントにテキストレスポンスを返します。他にも c.JSON() 、c.HTML() などの返し方があります。 |
e.Start(...) |
サーバーを起動し、指定されたポートでリクエストを受け付けます。 |
シンプルかつ強力なルーティング
Echoのルーティングはとても直感的です。ルートの設定はメソッドチェーンのように積み上げていけるため、小規模から中規模のアプリには特に適しています。
リクエスト処理の基本
Echoでは、リクエストデータの取得がとてもシンプルです。クエリパラメータ・パスパラメータ・JSONボディなど、さまざまな入力方法に対応しており、Echo独自のContext
を通じて取得できます。
クエリパラメータの取得
+ e.GET("/search", func(c echo.Context) error {
+ keyword := c.QueryParam("q")
+ return c.String(http.StatusOK, "query: "+keyword)
+ })
以下のURLにアクセスします。
curl 'http://localhost:8080/search?q=golang'
レスポンス
"query": "golang"
パスパラメータの取得
パスに埋め込まれた値を取得するには、:param
という形でルーティングを定義します。
+ e.GET("/users/:id", func(c echo.Context) error {
+ id := c.Param("id")
+ return c.String(http.StatusOK, "user_id: "+id)
+ })
以下のURLにアクセスします。
curl http://localhost:8080/users/123
レスポンス
"user_id": "123"
フォームデータの取得
フォームから送られるデータは c.FormValue
で取得します。
+ e.POST("/login", func(c echo.Context) error {
+ username := c.FormValue("username")
+ password := c.FormValue("password")
+ return c.String(http.StatusOK, "user_name: "+username+", password: "+password)
+ })
curl -X POST -d "name=Gopher&password=p1234567" http://localhost:8080/login
レスポンス
user_name: , password:p1234567
JSONの取得と構造体へのバインド
クライアントからJSON形式でデータが送られてくる場合、c.Bind
で構造体にバインドします。
+ type Message struct {
+ Title string `json:"title"`
+ Content string `json:"content"`
+ }
func main() {
r := gin.Default()
※一部省略
+ e.POST("/messages", func(c echo.Context) error {
+ msg := new(Message)
+ if err := c.Bind(msg); err != nil {
+ return err
+ }
+ return c.JSON(http.StatusOK, msg)
+ })
}
curlでPOSTリクエストを送ります。
curl -X POST http://localhost:8080/messages \
-H "Content-Type: application/json" \
-d '{"title": "Hello", "content": "This is a test message"}'
レスポンス
{"title":"Hello","content":"This is a test message"}
レスポンスの書き方
Echoでは、JSON・HTML・文字列など様々な形式でレスポンスを返すことができます。ここでは代表的なレスポンスの書き方を紹介します。
JSONを返す
構造体を定義してJSONで返すことができます。
e.GET("/json", func(c echo.Context) error {
msg := Message{
Title: "Hello",
Content: "This is a JSON response",
}
return c.JSON(http.StatusOK, msg)
})
curlで/json
にアクセスします。
curl http://localhost:8080/json
レスポンス
{"title":"Hello","content":"This is a JSON response"}
c.JSON(status, obj)
は obj をJSONにエンコードして返します。
HTMLを返す
Echoではテンプレートエンジンを使ってHTMLを返すことも可能ですが、まずはシンプルにHTML文字列を返す方法です。
e.GET("/html", func(c echo.Context) error {
html := `<h1>Welcome</h1><p>This is HTML content.</p>`
return c.HTML(http.StatusOK, html)
})
ブラウザでアクセスして確認します。
任意のステータスコードを使う
例えば、データが見つからなかったときに404を返すこともできます。
e.GET("/notfound", func(c echo.Context) error {
return c.String(http.StatusNotFound, "Not Found")
})
curlで/notfound
にアクセスします。
curl -i http://localhost:8080/notfound
レスポンス
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=UTF-8
Date: Mon, 16 Jun 2025 00:31:15 GMT
Content-Length: 9
Not Found
ミドルウェアの活用
Echoはミドルウェアを簡単に導入できる仕組みが整っており、ログ出力、リカバリ(panic処理)、CORS、Basic認証など、Webアプリで頻出の機能を“薄いコード”で導入できます。
ミドルウェアとは?
ミドルウェアとは、リクエストとレスポンスの「間」に挟まる処理のことです。全てのリクエストに対して共通の処理を実行するのに適しています。
たとえば:
- リクエストログを記録する
- 認証・認可を行う
- panicが起きた際に500エラーを返すようにする
- CORSヘッダーを追加する
標準ミドルウェアの使い方
Echoには最初からいくつかの便利なミドルウェアが用意されています。
import (
"net/http"
"github.com/labstack/echo/v4"
+ "github.com/labstack/echo/v4/middleware"
)
e := echo.New()
+ e.Use(middleware.Logger())
+ e.Use(middleware.Recover())
※一部省略
+ e.GET("/panic", func(c echo.Context) error {
+ panic("something went wrong")
+ })
curlでアクセスするとログが出力されます。
{"time":"2025-06-16T09:46:37.223514+09:00","id":"","remote_ip":"::1","host":"localhost:8080","method":"GET","uri":"/notfound","user_agent":"curl/8.7.1","status":404,"error":"","latency":9333,"latency_human":"9.333µs","bytes_in":0,"bytes_out":9}
また/panic
にアクセスすると下記のメッセージがクライアント側で出力されます。
curl http://localhost:8080/panic
レスポンス
{"message":"Internal Server Error"}
独自ミドルウェアの定義
独自のミドルウェアを定義することもできます。
このように next を挟んで前後に処理を入れることで、処理の前後関係を制御できます。
func myMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// 前処理
println("Before handler")
// ハンドラー本体の呼び出し
err := next(c)
// 後処理
println("After handler")
return err
}
}
e.Use(myMiddleware)
ミドルウェアをルート単位で適用することも可能です。
+ g := e.Group("")
+ g.Use(myMiddleware)
- e.GET("/notfound", func(c echo.Context) error {
+ g.GET("/notfound", func(c echo.Context) error {
return c.String(http.StatusNotFound, "Not Found")
})
curlで/notfound
にアクセスします。
curl -i http://localhost:8080/notfound
サーバー側で特定のルートだけログが表示されていることが確認できます。
さいごに
本記事では、Go × Echo を使った Web サーバの構築手順を、基本構造からミドルウェアの活用まで丁寧に解説しました。
Echo は学習コストが低く、柔軟で高速な Web フレームワークです。Gin と比べても、よりシンプルなコードで直感的に書ける点が魅力です。初学者はもちろん、中規模なプロジェクトにも十分に対応できるポテンシャルがあります。
この記事を通じて、Echo の書き方や考え方が少しでもつかめたなら幸いです。ぜひ自身のプロジェクトや学習に取り入れて、手を動かしながら感覚を深めていってください。
次回以降では、Echoを使ったより実践的なAPI設計や、テスト、構成管理、デプロイ手法にも触れていく予定です。
関連する技術ブログ
Go × Gin 基礎編:高速APIサーバーの作り方を徹底解説
Go言語の特性を活かし、Ginフレームワークでシンプルかつ強力なAPIサーバーを構築する方法をステップバイステップで解説します。インストールからミドルウェア、サンプルAPI作成まで、実践的な内容を盛り込んだ入門記事です。
shinagawa-web.com
Go × Gin でMVC構成のブログ記事投稿用Web APIを構築する:基礎からスケーラブル設計まで
Go言語とGinフレームワークを使って、MVC構成のWeb APIを一から構築していきます。ディレクトリ設計からルーティング、ミドルウェアの活用まで、実践的なコードで丁寧に解説。スケーラブルな設計の基本を学びたい方におすすめの入門編です。
shinagawa-web.com
Go × Gin × MVC構成で実践する堅牢なテスト設計と実装ガイド
単体テスト、統合テスト、E2Eテストを通して、GinベースのMVC構成アプリを堅牢に育てる方法を解説します。httptestの使い方やモックの作り方、共通処理の抽出など、実務に活かせるテスト設計のエッセンスを凝縮しました。
shinagawa-web.com
Go + Ginアプリを本番品質に仕上げる:設定・構成・CI導入まで
アプリを「動く」から「本番で保てる」品質へ引き上げるために、設定ファイルの整理、依存の分離、GitHub ActionsによるCI導入までを解説します。小規模開発からチーム開発へスムーズに移行したい方に向けた応用編です。
shinagawa-web.com
Go言語でWeb APIサーバーを作る完全ガイド|設計・開発フロー・テスト・CI/CDまで徹底解説
Go言語でWeb APIサーバーを作りたい方向けに、設計方針、APIスキーマ(OpenAPI/Swagger)、エンドポイント実装、テスト(単体・統合・E2E)、ミドルウェアの設定、CI/CD自動化までを詳しく解説します。初心者でもわかりやすく、開発フローを段階的にまとめた完全ガイドです。
shinagawa-web.com
弊社の技術支援サービス
無駄なコストを削減し、投資対効果を最大化する
クラウド費用の高騰、不要なSaaSの乱立、開発工数の増加――これらの課題に悩んでいませんか?本サービスでは、クラウドコストの最適化、開発効率向上、技術選定の最適化 を通じて、単なるコスト削減ではなく、ROIを最大化する最適解 をご提案します。
shinagawa-web.com
最新技術の導入・検証を支援するPoCサービス
Remix、React Server Components、TypeScript移行、クラウドサービス比較、マイクロサービス、サーバーレス、デザインシステムなど、最新技術のPoC(概念実証)を通じて、最適な技術選定と導入を支援します。貴社の開発課題に合わせた検証・実装で、ビジネスの成長を加速させます。
shinagawa-web.com
開発生産性を最大化するための技術支援
開発チームの生産性向上、コードの品質管理、インフラの最適化まで、様々な側面からサポートします。コードベースのリファクタリングから、テスト自動化、オンボーディング強化まで、プロジェクトの成功に必要なすべての支援を提供。御社の開発現場が効率的に機能するように、技術的な障害を取り除き、スムーズな開発を実現します。
shinagawa-web.com
開発品質向上支援 – 効率的で安定したプロダクトを実現
フロントエンドからバックエンド、データベースまで、開発プロセス全体を最適化し、安定したプロダクト作りをサポートします。コードレビューの仕組み、型定義の強化、E2Eテスト環境の構築など、開発の各ステップにおけるベストプラクティスを導入することで、より効率的でバグの少ない、そしてユーザー満足度の高いサービス提供を支援します。
shinagawa-web.com
Webアプリのセキュリティ強化支援
Webアプリの脆弱性対策からインフラのセキュリティ強化まで、包括的なセキュリティ支援を提供。OWASP Top 10対策、JWT認証の最適化、APIのアクセス制御、依存パッケージの監査、セキュアコーディングの標準化など、実践的なアプローチで開発現場の安全性を向上させます。
shinagawa-web.com
目次
お問い合わせ