はじめに
Go言語はシンプルで高速な処理能力を誇り、WebサービスやAPI開発において非常に頼もしい存在です。そのGoの強みを最大限に引き出してくれるのが、軽量かつ高性能なWebフレームワーク「Gin」です。
本記事では、Go × Ginの魅力と基礎的な使い方を、初心者でも取り組みやすいように順序立てて解説します。インストールからHello Worldの作成、リクエスト・レスポンスの基本、そしてミドルウェアの活用まで、すぐに試せる具体例を交えながら進めていきます。
「高速でシンプルなAPIサーバーを作りたい」と思っている方にとって、この記事が役立つガイドになることを願っています。さあ、一緒にGinの世界をのぞいてみましょう。
Go + Ginを選ぶ理由
WebアプリケーションやAPIサーバーを作る際、使用する言語やフレームワークは非常に重要です。ここで、GoとGinを選ぶ理由を整理しておきます。
1️⃣ Goの魅力
- 高いパフォーマンス:Goはコンパイル言語であり、軽快で高速な実行が可能です。
- シンプルな文法:最小限の記法で堅牢なコードを書けるため、学習コストが抑えられます。
- 並行処理に強い:GoroutineやChannelを活用することで、スケーラブルな処理が実現しやすいです。
2️⃣ Ginの強み
- 驚異的な速度:Ginは「極めて高速なWebフレームワーク」として知られています。
- 豊富な機能:ルーティング、ミドルウェア、JSONハンドリングなど、APIサーバーに必要な機能が網羅されています。
- シンプルなAPI設計:わかりやすいAPIで、すぐに実践的な開発に取りかかれます。
3️⃣ Go × Ginの相性の良さ
GoのシンプルさとGinのスピード・機能性は非常に相性が良く、パフォーマンスと保守性を両立したAPIサーバー構築を支えてくれます。
この記事では、この強力な組み合わせを活かし、実際にAPIサーバーを作る流れを丁寧に解説していきます。次は、まずGinを動かすところから始めていきます。
Ginのインストールと初期設定
ここでは、Ginをプロジェクトにインストールし、最小限のサーバーを動かすところまでを進めていきます。
Goのバージョン確認
まずは、Goのバージョンを確認します。GinはGo 1.18以降を推奨しているため、以下のコマンドで現在のGoバージョンを確認しておきます。
go version
例)
go version go1.23.0 darwin/arm64
プロジェクトディレクトリの作成
新しいプロジェクト用のディレクトリを作ります。例として my-gin-app という名前のディレクトリを作成します。
mkdir go-gin-basic-guide
cd go-gin-basic-guide
Goモジュールの初期化
まだGoモジュールを初期化していない場合は、以下を実行します。
go mod init go-gin-basic-guide
Ginのインストール
Ginをインストールします。
go get -u github.com/gin-gonic/gin
最小限のサーバーを作成
main.goを作成し、以下の内容を書きます。
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // デフォルトで :8080 ポート
}
サーバーを起動する
以下のコマンドでサーバーを起動します。
go run main.go
ブラウザやcurlで http://localhost:8080/ping にアクセスし、JSONレスポンスが表示されることを確認します。
curl http://localhost:8080/ping
これで、Ginを動かすための基本的な準備は整いました。次は、Ginの基本構造をもう少し深掘りしていきます。
補足: 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
試しにURLのパスを/ping
-> /pong
に変更してみます。
func main() {
r := gin.Default()
- r.GET("/ping", func(c *gin.Context) {
+ r.GET("/pong", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // デフォルトで :8080 ポート
}
すると、/pong
でレスポンスが返って来ることを確認できます。
curl http://localhost:8080/pong
動作確認が終わったら元に戻しておきます。
Ginの基本構造を理解する
Ginのアプリケーションは、ルーター、ハンドラ、コンテキストを中心に構成されます。ここでは、それぞれの役割と仕組みを詳しく整理し、実際にリクエストを変更しながら動作確認できる例も加えます。
ルーター(Router)
Ginのエントリーポイントは「ルーター」です。gin.Default() を使うと、ロガーやリカバリーミドルウェアがあらかじめ組み込まれたルーターを簡単に初期化できます。
r := gin.Default()
ハンドラ(Handler)
ルーターに登録したエンドポイントに対応するのが、ハンドラ関数です。これは、HTTPリクエストを受け取ってレスポンスを返す処理です。
例えば以下では、/ping というパスにアクセスしたときに「pong」というJSONレスポンスを返します。
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})
ここで /ping
はURLのパス部分にあたります。ブラウザやcurlで http://localhost:8080/ping
にアクセスして、動作を確認します。
コンテキスト(Context)
*gin.Context
は、リクエストやレスポンスに関する情報を扱うための便利な構造体です。
例えば、以下のようにクエリパラメータを取得できます。
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
+ r.GET("/hello", func(c *gin.Context) {
+ name := c.Query("name") // ?name=値 で取得
+ c.JSON(200, gin.H{"message": "Hello, " + name})
+ })
r.Run() // デフォルトで :8080 ポート
}
curl 'http://localhost:8080/hello?name=Gopher'
レスポンスは以下のようになります。
{"message": "Hello, Gopher"}
クエリパラメータを変えて再リクエストすれば、レスポンスも変わることを確認できます。
グルーピング(Grouping)
エンドポイントが多くなると、共通のパスをまとめて管理したくなります。Ginのグルーピングを使うと、パスの共通部分をまとめることができます。
以下の例では、/api という共通パスをグルーピングし、その中で GET /api/users
と POST /api/users
を定義しています。
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.GET("/hello", func(c *gin.Context) {
name := c.Query("name") // ?name=値 で取得
c.JSON(200, gin.H{"message": "Hello, " + name})
})
+ api := r.Group("/api")
+ {
+ api.GET("/users", func(c *gin.Context) {
+ c.JSON(200, gin.H{"message": "GET /api/users"})
+ })
+
+ api.POST("/users", func(c *gin.Context) {
+ c.JSON(200, gin.H{"message": "POST /api/users"})
+ })
+ }
r.Run() // デフォルトで :8080 ポート
}
以下のURLにアクセスすると、それぞれのエンドポイントが正しく動作していることを確認できます。
curl http://localhost:8080/api/users
curl -X POST http://localhost:8080/api/users
リクエスト処理の基本
ここでは、Ginを使ったリクエスト処理の基本を整理します。
実際にパラメータを取得し、レスポンスを返す方法を動作確認しながら見ていきます。
パスパラメータの取得
パスに埋め込まれた値を取得するには、:param
という形でルーティングを定義します。
+ r.GET("/users/:id", func(c *gin.Context) {
+ id := c.Param("id")
+ c.JSON(200, gin.H{"user_id": id})
+ })
以下のURLにアクセスします。
curl http://localhost:8080/users/123
レスポンス
{"user_id": "123"}
クエリパラメータの取得
クエリパラメータ(?key=value
の形)を取得するには、c.Query
を使います。
+ r.GET("/search", func(c *gin.Context) {
+ keyword := c.Query("q")
+ c.JSON(200, gin.H{"query": keyword})
+ })
以下のURLにアクセスします。
curl 'http://localhost:8080/search?q=Gin'
レスポンス
{"query": "Gin"}
クエリパラメータを変えると、レスポンスが動的に変わることを確認できます。
フォームパラメータの取得(POST)
フォームから送られるデータは c.PostForm
で取得します。
+ r.POST("/submit", func(c *gin.Context) {
+ name := c.PostForm("name")
+ c.JSON(200, gin.H{"submitted_name": name})
+ })
curlでPOSTリクエストを送ります。
curl -X POST -d "name=Gopher" http://localhost:8080/submit
レスポンス
{"submitted_name": "Gopher"}
JSONリクエストの取得
クライアントからJSON形式でデータが送られてくる場合、c.BindJSON
で構造体にバインドします。
+ type User struct {
+ Name string `json:"name"`
+ Age int `json:"age"`
+ }
func main() {
r := gin.Default()
※一部省略
+ r.POST("/json", func(c *gin.Context) {
+ var user User
+ if err := c.BindJSON(&user); err != nil {
+ c.JSON(400, gin.H{"error": err.Error()})
+ return
+ }
+ c.JSON(200, gin.H{"name": user.Name, "age": user.Age})
+ })
r.Run() // デフォルトで :8080 ポート
}
curlでJSONを送ります。
curl -X POST -H "Content-Type: application/json" -d '{"name":"Gopher","age":5}' http://localhost:8080/json
レスポンス
{"name": "Gopher", "age": 5}
まとめ
リクエスト処理の基本として、以下のポイントを押さえました。
✅ パスパラメータ: c.Param
✅ クエリパラメータ: c.Query
✅ フォームパラメータ: c.PostForm
✅ JSONリクエスト: c.BindJSON
これらを組み合わせることで、様々なAPIリクエストを柔軟に受け取れます。
次は、レスポンスの書き方を見ていきます。
レスポンスの書き方
ここでは、Ginを使ったレスポンスの書き方を整理します。
APIサーバーとして最も重要な「クライアントに何を返すか」を明確にしていきます。
JSONレスポンス
APIではJSON形式のレスポンスを返すことが一般的です。c.JSON
を使って以下のように返します。
r.GET("/json", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "Hello, Gin!",
})
})
- 第1引数: HTTPステータスコード(例: 200)
- 第2引数: 返すJSONデータ(
map[string]interface{}
や構造体)
文字列レスポンス
テキストを直接返す場合は、c.String
を使います。
r.GET("/text", func(c *gin.Context) {
c.String(200, "This is a plain text response.")
})
シンプルなメッセージの返却に便利です。
HTMLレスポンス
HTMLを返す際には c.HTML
を使います。
LoadHTMLGlob でテンプレートを読み込み、HTMLを返す例です。
+ r.LoadHTMLGlob("templates/*")
+ r.GET("/html", func(c *gin.Context) {
+ c.HTML(200, "index.tmpl", gin.H{"title": "Hello, HTML!"})
+ })
以下のようなディレクトリ構成にします。
my-gin-app/
├── main.go
└── templates/
└── index.tmpl
templates/index.tmpl
のサンプル:
<!DOCTYPE html>
<html>
<head>
<title>{{ .title }}</title>
</head>
<body>
<h1>{{ .title }}</h1>
<p>This is a sample HTML response rendered by Gin.</p>
</body>
</html>
ブラウザ上で Hello, HTML!
という見出しと本文が表示されます。
まとめ
Ginを使ったレスポンスの書き方として、以下のポイントを押さえました。
✅ JSON: c.JSON
✅ 文字列: c.String
✅ HTML: c.HTML
✅ ステータスコードのみ: c.Status
✅ 統一的なエラーレスポンス: 構造体を定義して返す
これらを使い分けることで、APIの設計・運用がスムーズになります。
次は、Ginのミドルウェアの活用方法を見ていきます。
ミドルウェアの活用
Ginでは、ミドルウェアを使うことでリクエスト前後に共通の処理を差し込むことができます。
ここでは、標準で用意されているミドルウェアや、自作のミドルウェアを導入する方法を整理します。
組み込みミドルウェア
Ginには便利な組み込みミドルウェアがいくつかあります。代表的なものを紹介します。
ロガー(Logger)
リクエストをログ出力するミドルウェアです。
r := gin.New()
r.Use(gin.Logger())
gin.Default()
にはすでにロガーが含まれているため、改めて追加する必要はありません。
APIにアクセスするとログがコンソールに表示されます。
リカバリー(Recovery)
パニックが発生してもサーバーを落とさず、500エラーレスポンスを返すミドルウェアです。
r.Use(gin.Recovery())
こちらも gin.Default()
に含まれています。
自作ミドルウェアの作り方
共通の前処理や後処理を行いたい場合は、自作のミドルウェアを作成できます。
以下は、リクエストが来るたびに「Before request...」を表示する簡単な例です。
+ func MyCustomMiddleware() gin.HandlerFunc {
+ return func(c *gin.Context) {
+ println("Before request...")
+ c.Next()
+ println("After request...")
+ }
+ }
func main() {
r := gin.Default()
+ r.Use(MyCustomMiddleware())
APIにリクエストを送ると、「Before request...」「After request...」と表示されていることが確認できます。
グローバルに適用するのではなく、特定のルートだけにミドルウェアを設定することもできます。
func main() {
r := gin.Default()
- r.Use(MyCustomMiddleware())
※一部省略
+ r.GET("/special", MyCustomMiddleware(), func(c *gin.Context) {
+ c.JSON(200, gin.H{"message": "This route uses a custom middleware."})
+ })
r.Run() // デフォルトで :8080 ポート
}
特定のルートだけ「Before request...」「After request...」と表示されていることが確認できます。
さいごに
ここまで、Ginを使ったGoのAPIサーバー開発の基礎を一通り見てきました。
実際にコードを書いて動かしながら学ぶ中で、以下のポイントが整理できたかと思います。
✅ Ginの基本構造(ルーター・ハンドラ・コンテキスト)
✅ 各種リクエストパラメータの取得方法
✅ JSONやテキスト、HTMLレスポンスの書き方
✅ ミドルウェアの活用方法と管理
これらはすべて、API開発の基盤になる考え方です。小さな機能の積み重ねが、将来の大きなシステムにつながります。
次のステップへ
今回学んだ基礎知識をベースに、次はより実践的な応用編へ進めます。
- 認証・バリデーションの実装
- Ginのテスト手法
- 本番運用のポイント
- スケーラブルなアーキテクチャの考え方 など…
関連する技術ブログ
Go × Echoで始めるWebサーバ構築入門:シンプル・高速なAPI開発を最短で学ぶ
Go言語で軽量・高速なWebアプリケーションを構築したい方へ。人気フレームワーク「Echo」の導入から基本構造、ルーティング、レスポンス、ミドルウェアの使い方までを、実践的なサンプルコードとともにわかりやすく解説します。Ginとの違いにも触れながら、最小構成でWebサーバを立ち上げるまでを丁寧にガイドします。
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
目次
お問い合わせ