GoでWeb APIサーバーを作りたいけど、どうやって進めたらいいか迷うこともありますよね。
今回は、初心者の方でも取り組みやすいように、設計の考え方から導入手順までを順を追って解説します。
まず押さえておきたいポイント
GoでWeb APIサーバーを作るときは、以下の2つを意識すると開発がグッとやりやすくなります。
✅ 疎結合 & 保守性を重視する
✅ ビジネスロジック(ドメイン)とインフラ周りを分ける
これを意識しておくと、後から機能を拡張するのも楽になります。
疎結合 & 保守性を重視するとは?
疎結合とは、アプリの各部分が「なるべく依存しすぎない」ように作ることです。
例えば、APIのルーティング部分(Ginなど)と、データベース操作(GORMなど)を直接つなぎすぎると、修正や拡張が大変になりがちです。
代わりに、API層(ハンドラ)・ビジネスロジック層(Usecase)・データアクセス層(Repository)といった役割ごとの分離をすると、以下のようなメリットがあります。
- どこか1箇所を修正しても、他の部分への影響が少ない
- テストも役割ごとに作りやすい(例:DBをモック化してビジネスロジックだけテストする、など)
ビジネスロジック(ドメイン)とインフラ周りを分ける
-
ビジネスロジックとは、そのアプリ特有の「こう動くべき」という処理部分です。
例:アルバム作成時にタイトルは必須、カテゴリーが正しいかチェック…など。 -
インフラ周りとは、外部とやり取りする部分です。
例:DBにデータを保存する処理、APIのルーティング、ファイル操作など。
これを分けるとどうなるかというと…
例えば「DBをMySQLからPostgreSQLに変えたい!」となったときでも、インフラ部分(Repository)だけ修正すれば済むことが多くなります。
要件・仕様を整理する
まずは、どんなAPIを作りたいのか、どんなデータを扱うのかをまとめます。
ER図やデータフローを簡単にでも書いておくと、開発がスムーズです。
どんなAPIを作りたいのか考える
APIを作る目的や機能をざっくりと洗い出します。
例えば、ブログサイトなら、以下のような操作が考えられます。
- 新しいブログ記事を投稿するAPI
- 投稿された記事を取得するAPI
- 記事を編集するAPI
- 記事を削除するAPI
- カテゴリーやタグを管理するAPI
「どんな操作が必要?」と考えて、APIのエンドポイント(URL)をリストアップしておくとスムーズです。
どんなデータを扱うのか決める
次に、ブログの記事データをどう扱うかを整理します。
ブログサイトなら、記事データの基本的な要素はこんなイメージです。
- 記事タイトル(Title)
- 記事本文(Content)
- 公開日(PublishedAt)
- カテゴリー(Category)
- タグ(Tags)
- 著者情報(Author)
「このAPIでどんなデータを返すか・受け取るか」を意識しておくと、レスポンスやリクエストの形が決めやすいです。
ER図やデータフローを描いてみる
ここで「頭の中のイメージ」を図にしておくと、全体像がスッキリ見えます。
- ER図(Entity-Relationship 図)
例えば、記事とカテゴリーの関係はこう描けます。
Post (ID, Title, Content, PublishedAt, AuthorID, CategoryID)
Category (ID, Name)
Author (ID, Name)
- データフロー図
APIがどんな流れでデータを処理するかを絵にしておくと便利です。
Client → APIサーバー(エンドポイント) → ビジネスロジック → DB
なぜここをしっかりやるのか?
- 途中で「この記事APIって何を返すんだっけ?」と迷わない
- フロントエンドや他のチームメンバーと認識を共有しやすい
- 設計書として残せるので、将来のメンテナンスが楽になる
最小限の動作確認(Hello World)
いきなり複雑なAPIを作ろうとすると、どこかで詰まりやすくなります。
まずは「サーバーが起動してリクエストを受け付ける」という最小限の動作を確認しましょう。
フレームワークとしては、GoではGinやEchoが人気です。
どちらも簡単なコードでAPIを試せます。
Ginのサンプル
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default() // Ginのデフォルト設定(ロギングやリカバリ機能もON)
// /health エンドポイントを作成
r.GET("/health", func(c *gin.Context) {
c.JSON(200, gin.H{"status": "ok"})
})
// サーバー起動(ポート8080)
r.Run(":8080")
}
✅ ポイント
r.GET
で「GETリクエストに応答するルート」を定義します。/health
にアクセスすると、{"status": "ok"}
というJSONが返ります。
より詳しくGinの基礎を知りたい方は、こちらの記事をご覧ください。
Echoのサンプル
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New() // Echoのインスタンスを作成
// /health エンドポイントを作成
e.GET("/health", func(c echo.Context) error {
return c.JSON(http.StatusOK, map[string]string{"status": "ok"})
})
// サーバー起動(ポート8080)
e.Start(":8080")
}
✅ ポイント
- Ginと似た形で「GETエンドポイント」を定義しています。
- c.JSONでJSONレスポンスを返せます。
- Echoは
map[string]string
で簡単にJSONを作れるので、こちらも使いやすいです。
まずは「Hello, World!」の代わりに /health が返るだけでもOKです。
ここまでできたら「サーバーは起動できる」と自信が持てます
まずは「サーバーが立ち上がる」ことを確認するだけでOK。
ルーティングがちゃんと機能するか?レスポンスはちゃんと返せるか?を試すことで、環境構築やコードの基本が整います。
設計方針を決める
APIサーバーを作るとき、最初に「どんな設計方針で進めるか」を考えておくと、後で修正が入っても大丈夫なしなやかで強いアプリになります。
なぜ設計方針が大事?
小さいアプリなら「全部1つのファイルに書く」でも動きますが、機能が増えると必ず困ります。
- どこに何が書いてあるかわからない…
- ちょっと修正したら別の機能が壊れた…
- テストもしづらい…
こんなトラブルを避けるために、設計方針=プロジェクトの骨組みをしっかり決めておく必要があります。
代表的な設計スタイル
クリーンアーキテクチャ(レイヤードアーキテクチャ)
役割ごとに層を分けることで、依存関係がはっきりして保守性が高まります。
├── handler (APIの入口)
├── usecase (ビジネスロジック)
├── entity (ドメインモデル)
├── gateway (DBや外部APIのやりとり)
├── pkg (共通ライブラリ・ツール群)
✅ ポイント
- 例えば「DBをMySQL→PostgreSQLに変えたい」となっても、gatewayだけ直せばOK
- usecaseやentityが「アプリの本質的なロジック」を守るので、インフラの変更に強くなる
MVC(シンプルな構成)
「モデル・ビュー・コントローラ」の役割で分ける構成。小規模アプリならこれでもOK。
├── controllers (リクエストを受け取る部分)
├── models (DBやデータ構造)
├── views (HTMLテンプレートなど)
✅ ポイント
- 1ファイルが巨大にならず、見通しが良い
- クリーンアーキテクチャほど厳密じゃなくてもOK
Go × Gin を使って、ブログ記事投稿APIをMVC構成で組み立てる基礎的な流れをご紹介している記事。
設計方針を決めるときのヒント
-
自分が「どこで何をするか」イメージできるか?
「この処理はusecaseでやる」「DB操作はgateway」みたいにイメージできると、迷いにくくなります。 -
最初から完璧を目指さなくてOK
とりあえず分けて、後で「ここはまとめよう」「ここは層を増やそう」と見直せばいいです。もちろん途中でMVCからクリーンアーキテクチャに移行することも可能です。
APIスキーマを決める(できればOpenAPIを活用)
Web APIを作るときに、「APIの仕様書をどうするか?」 はとても重要なポイントです。
特にチーム開発やフロントエンド・モバイルとの連携があるなら、OpenAPI(旧Swagger) の活用を強くおすすめします。
APIスキーマとは?
APIスキーマは、以下のような「APIの設計図」です。
- どんなエンドポイントがある?
- どんなリクエストボディ・レスポンスがある?
- どんなデータ型・バリデーションが必要?
これを文章で書くのではなく、マシン可読な形式(YAMLやJSON)でまとめるのがOpenAPI仕様です。
OpenAPI(Swagger)のメリット
-
ドキュメントとして誰でも見れる
swagger-uiを使えばブラウザ上でわかりやすく表示されるので、フロントエンドやデザイナー、テスターも迷わない。 -
ツールで一括管理できる
例えば oapi-codegen などを使うと、OpenAPIからGoの型(構造体やクライアントコード)を自動生成できます。 -
テストやモックサーバーも作りやすい
OpenAPIを使うと、自動でモックサーバーを立てるツール(Prismなど)も使えます。
これで「バックエンドができる前にフロント開発を進める」なんてことも可能です。
例)OpenAPIファイル(例: openapi.yaml)の内容
openapi: 3.0.0
info:
title: My Blog API
version: 1.0.0
paths:
/posts:
get:
summary: 記事の一覧を取得
responses:
'200':
description: 一覧取得成功
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Post'
components:
schemas:
Post:
type: object
properties:
id:
type: integer
title:
type: string
content:
type: string
publishedAt:
type: string
format: date-time
Go用のコード自動生成(oapi-codegenなど)
OpenAPIからGoコードを自動生成するツールとして、oapi-codegenがよく使われます。
- openapi.yamlから、Goの型(リクエスト・レスポンス用の構造体)を生成
- APIクライアントやサーバースタブも生成可能
✅ メリット
- 型が自動で生成されるので、API仕様の変更があっても即対応できる
- 手書きのミスがなくなり、バグを減らせる
エンドポイントごとに実装する
まずは小さく始める
例えばブログAPIを作るとき、全部一気に作ろうとすると大変です。
まずは「新規作成APIだけ動かす」のように、一つずつ実装していきましょう。
実装するエンドポイントの例
✅ POST /blogs(新規作成)
- 新しいブログ記事を登録するAPI
- 受け取るデータ: タイトル・本文・カテゴリーなど
- 成功時のレスポンス: 作成された記事のIDや詳細情報
✅ GET /blogs/:id(取得)
- 記事の詳細を取得するAPI
:id
は記事のID(URLパラメータ)- データベースからそのIDの記事を取得して返す
✅ PATCH /blogs/:id(更新)
- 記事を編集するAPI
- 更新したい項目だけをリクエストボディに含めて送信
- DBでその記事を更新して返す
✅ DELETE /blogs/:id(削除)
- 記事を削除するAPI
:id
の指定で記事をDBから削除- 削除後は204 No Contentなどを返す
実装の基本フロー
どのエンドポイントでも、基本はこの流れです。
- ルーティング設定(GinやEchoでエンドポイントを登録)
- リクエストを受け取る(JSONやURLパラメータを取り出す)
- ビジネスロジックを実行(Usecase層)
- DBにデータを保存・取得・削除(Repository層)
- レスポンスをJSONで返す
ミドルウェアとエラーハンドリング
APIサーバーを実際に運用するなら、必須の機能がいくつかあります。
それを一括で担ってくれるのが ミドルウェア です。
ミドルウェアとは
ミドルウェアは、リクエストがハンドラに届く前や、レスポンスを返す直前に動く機能です。
サーバー全体に共通でかかる「中間処理」なので、複数のエンドポイントで同じ処理を何度も書く必要がなくなります。
必須ミドルウェアの例
✅ CORS(クロスオリジンリクエスト)
ブラウザから別ドメイン(オリジン)にAPIを呼ぶときに、CORS設定がないとブラウザがブロックします。
例えば:
- フロントが http://localhost:3000
- APIが http://localhost:8080
だと、ブラウザは「別オリジン」とみなしてリクエストを止めるんです。
CORSミドルウェアを入れることで、「このオリジンからのリクエストは許可するよ」 という設定をサーバー側でまとめて管理できます。
✅ ロギング
APIを呼ばれたときに、どんなリクエストが来て、どう応答したかを記録する仕組みです。
- 例: Ginのginzap(Zapロガーと連携)など
ログが残ることで…
- 何かトラブルが起きたときに、原因を追いやすい
- いつ、誰が、どんなAPIを呼んだか履歴がわかる
✅ Panic Recovery
Goアプリでは、時にpanic(致命的エラー)が発生することがあります。
もし対策しないと、サーバー全体が落ちちゃう。
Panic Recoveryミドルウェアは、panicが起きたときに自動でキャッチして、サーバーが落ちないように守ってくれます。
同時にエラーログを残してくれるので、原因も追いやすいです。
Ginではこんな感じで設定します。
r.Use(middleware.CorsMiddleware())
r.Use(middleware.GinZap())
r.Use(middleware.RecoveryWithZap())
テストを整備する
作ったAPIが「ちゃんと動くか」「バグがないか」…
それを自動的に確かめるのが テスト です。
テストを書いておくと、修正しても安心できるし、後で「何が壊れたか」もわかりやすいです。
単体テスト(Unit Test)
ビジネスロジックやユーティリティなど、1つの関数・クラス単位をテストします。
- 記事を新規作成するときに、タイトルが空だとエラーになるか?
- 公開日のバリデーションが正しく動くか?
など
✅ ポイント
- DBや外部APIにはつながない(= 速くて安定!)
- バグの原因をピンポイントで見つけやすい
func TestIsValidTitle(t *testing.T) {
valid := IsValidTitle("My Blog Post")
if !valid {
t.Error("expected title to be valid")
}
}
統合テスト(Integration Test)
複数のパーツが一緒に動くかを確認するテスト。APIで言うと、以下をまとめて動かします。
- ハンドラ
- ビジネスロジック
- DBアクセス
例えば、
- POST /blogs が 実際にDBに記事を作れるか?
- GET /blogs/:id が 作成された記事を正しく取得できるか?
✅ ポイント
- DBも動かすので「実際にアプリとして動くか」を確かめられる
- ただし単体テストよりは少し重い
E2Eテスト(End-to-End Test)
APIサーバー全体を「外から」叩くテストです。
例:
- フロントエンドから記事投稿をして、一覧に反映されるか?
- 本番に近い「ユーザー目線」で一連の流れを確認する
✅ ポイント
- 開発環境に近いので「リリース前の最後の保証」になる
- ただし重いので、すべてのケースをここでやる必要はない
ツール例:
- Goでも net/http で書ける
- PlaywrightやCypressを使うことも多いです
単体テストでの流れ
- DBには依存しないので、モックを作る(例: Goの testify/mock)
- Usecase関数だけテストする
統合テストでの流れ
- Docker ComposeでテストDBを立てる
- APIサーバーをテスト用設定(APP_ENV=integration など)で起動
- go testでAPIにリクエストを送る
- DBのデータを確認する
Go × Gin × MVC構成でテスト設計および実装方法をご紹介しています。合わせてご参考ください。
どうやって始める?
まずは ビジネスロジックの単体テストから始めます。
速く書けて「ここは正しい」と保証できるので、一番手軽です。
それが慣れたら、統合テストでAPI全体の動きを確かめます。
例えば「POST /blogs が本当にDBに記事を作っているか?」を確認します。
本番リリース前には、E2Eテストで最終チェックを行います。
まるで「本物のユーザーが使っている」状態で試せるので、安心感があります。
CI/CDを導入する
開発フローが安定してきたら、CI(継続的インテグレーション)/CD(継続的デリバリーまたはデプロイ)を取り入れるのがおすすめです。
これによって、「手動での手順ミス」をなくし、自動でテストやビルドを回せるようになります。
CI/CDとは?
CI(継続的インテグレーション)
-「コードをマージするたびに、テストやビルドを自動で行う仕組み」
-「テストが通ってる!=壊れてない!」という安心感が得られる。
CD(継続的デリバリー or デプロイ)
-「動くアプリを本番環境に自動デプロイする仕組み」
- 例: PRがマージされたら自動的に本番にデプロイされる。
何を自動化する?
GoのAPIサーバーだと、こんな作業を自動化します。
テストの実行
- go test ./... を自動で実行
- 失敗したらプルリクがマージできないようにする
Lint・静的解析
- golangci-lint などでコードの静的チェックを自動化
- コード品質を一定に保つ
Dockerビルド・動作確認
- docker build でイメージを作って起動する
- 必要なら docker-compose up でテストDB込みで統合テストを回す
デプロイ(必要に応じて)
- 本番やステージングへのデプロイを自動化
- 例: mainブランチにマージされたら本番へデプロイ
CI/CD導入のメリット
人為的なミスが減る
- 「テスト忘れてた!」「設定間違えた!」がなくなる
プルリク・マージの安心感
- 「ちゃんと全部テストが通ってる」とみんなで確認できる
本番でのトラブルが減る
- 本番リリースまでの手順が自動化されるから、安全性アップ!
最初の一歩
CI/CDを難しそうに感じるかもしれませんが、最初は「テストを自動化するだけ」でも十分なスタートです。
例えばGitHub Actionsなら、以下のような最小構成を置くだけで動きます。
name: Go CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: "1.19"
- run: go test ./...
まとめ
GoでWeb APIサーバーを作るときは…
✅ まずは小さく「Hello, World!」から
✅ 設計を決めて、順にAPIを作っていく
✅ ミドルウェア・テストを整備して信頼性アップ
✅ 仕組みを整えていくとチーム開発でも強い
こういう順番で、少しずつ「動くもの」を積み上げていくのが大事です。
最初から完璧を目指さず、まずは小さく作って育てるイメージで進めてみましょう。
関連する技術ブログ
開発フローを高速化・自動化する CI/CD 戦略:キャッシュ・並列実行・AI レビューの活用
ソフトウェア開発の高速化と安定化を実現するために、CI/CD の最適化は欠かせません。本記事では、npm / yarn / Docker のキャッシュ戦略を強化する方法や、並列実行によるパイプラインの高速化、変更のあった部分のみをテスト・ビルドする仕組みの導入について詳しく解説します。また、Blue-Green デプロイや Canary デプロイを活用した安全な本番環境へのリリース戦略、Terraform / Pulumi によるインフラの自動プロビジョニング、GitHub Secrets / AWS Parameter Store を用いたシークレット管理の最適化についても取り上げます。さらに、エラー発生時の自動ロールバック機能の実装、CI/CD 実行ログの可視化(Datadog / Grafana 連携)、Dependabot / Snyk を活用したセキュリティスキャンの自動化、AI(CodeGPT, DeepCode, Codium など)を用いた PR の自動レビューと改善提案まで、開発フローを効率化するための実践的なアプローチを紹介します。CI/CD の最適化を進め、開発スピードと信頼性を両立させたいエンジニア必見の内容です。
shinagawa-web.com
Go × Echoで始めるWebサーバ構築入門:シンプル・高速なAPI開発を最短で学ぶ
Go言語で軽量・高速なWebアプリケーションを構築したい方へ。人気フレームワーク「Echo」の導入から基本構造、ルーティング、レスポンス、ミドルウェアの使い方までを、実践的なサンプルコードとともにわかりやすく解説します。Ginとの違いにも触れながら、最小構成でWebサーバを立ち上げるまでを丁寧にガイドします。
shinagawa-web.com
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
弊社の技術支援サービス
無駄なコストを削減し、投資対効果を最大化する
クラウド費用の高騰、不要な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
目次
お問い合わせ