Contents
GinフレームワークとPostgreSQLでREST APIを構築する流れ
Go言語でWeb APIを開発する際、GinフレームワークとPostgreSQLの組み合わせは実装効率が高く、多くの企業や個人開発者に採用されています。特に2026年現在では、Go 1.22以降のバージョンで標準化されたモジュール管理と併せ、Ginやpgx(PostgreSQLクライアント)などのツールがさらに使いやすくなっています。本記事では、Ginフレームワークを活用したREST API構築の実践手順を解説し、プロジェクト全体像・環境設定・認証機能・テスト方法など、フルスタック開発に必要な知識を網羅します。
本記事の目的と実装範囲
本記事では、Go言語初心者から中級者向けに、Ginフレームワーク×PostgreSQLによるREST API構築に特化した内容を解説します。以下の手順で実装を行います:
- Go標準ライブラリでのHTTPサーバーの基礎
- Ginフレームワークの導入とルーティング設定
- PostgreSQLとの接続・CRUD処理の実装
- 型安全なJSONレスポンス処理方法
- 認証機能(JWT)の実装例
- httptestによるテストコードの書き方
読者には「すぐに実装できる」という視点で、具体的なコードサンプルと設計パターンを提供します。
必要な環境設定と前提条件
以下が開発に必要な環境・ツールです:
| 項目 | 種類 | 説明 |
|---|---|---|
| 言語 | Go | 最新版(2026年現在はGo 1.22以降を推奨) |
| フレームワーク | Gin | REST API開発に特化したWebフレームワーク |
| データベース | PostgreSQL | リレーショナルDBとして採用。pgxライブラリで接続 |
| ツール | Go Modules、Docker(オプション) | 開発環境構築に必要 |
必要なパッケージは
go getまたはgo mod tidyを使ってインストールしてください。
Go標準ライブラリでのHTTPサーバー構築基礎
Ginフレームワークを導入する前に、Go標準ライブラリで最小限のHTTPサーバー構築方法を確認します。これはAPI開発の基本であり、今後の理解に不可欠です。
net/httpパッケージの基本的な使い方
Go言語にはnet/httpという標準パッケージが組み込まれており、これだけで簡単にWebサーバーを作成できます。以下は、シンプルなHTTPサーバーの実装例です:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package main import ( "fmt" "net/http" ) func helloHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World!") } func main() { http.HandleFunc("/", helloHandler) http.ListenAndServe(":8080", nil) } |
このコードは、ローカルのlocalhost:8080にアクセスすると「Hello, World!」と表示されます。このようにして、Go標準ライブラリでもWebサーバーを構築できますが、実際にはGinのようなフレームワークを使うことで、より複雑なAPI開発が効率的になります。
Ginフレームワークの導入とルーティング設定
GinはGo言語における高速でシンプルなWebフレームワークとして知られています。以下に、プロジェクトにGinを導入し、ルーティングを設定する方法を紹介します。
Ginのインストール手順
Ginフレームワークをプロジェクトに追加するには、go getコマンドを使用します:
|
1 2 |
go get github.com/gin-gonic/gin |
これで、ginパッケージがGoモジュールとして自動的に追加されます。
GET/POSTメソッドのルート定義
Ginはルーティングをシンプルに設定できるため、GETとPOSTそれぞれに対して以下のコードを記述します:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package main import ( "github.com/gin-gonic/gin" ) func main() { r := gin.Default() // GETメソッドでアクセスするエンドポイント r.GET("/users", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "GET request received", }) }) // POSTメソッドでアクセスするエンドポイント r.POST("/users", func(c *gin.Context) { c.JSON(201, gin.H{ "message": "POST request received", }) }) r.Run(":8080") } |
このコードでは、/usersというエンドポイントにアクセスすることで、GETとPOSTそれぞれの処理が実行されます。Ginのルーティングは柔軟で、複雑な条件も対応可能です。
ミドルウェアの基本構成
ミドルウェアは、リクエストが実際のハンドラーに渡される前の処理を担当します。たとえば、ログ出力や認証処理などに使用します。
|
1 2 3 4 5 |
r.Use(func(c *gin.Context) { fmt.Println("Request received") c.Next() }) |
上記コードでは、任意のミドルウェア関数をGinに登録することで、リクエストが各エンドポイントに到達する前に処理を行います。このようにして、柔軟なAPI構築が可能です。
PostgreSQLとの接続・CRUD処理実装
PostgreSQLとの接続にはpgxライブラリを使用します。以下では、データベース接続からCRUD操作の実装までを解説します。
pgxライブラリの初期化手順
pgxはPostgreSQLと通信するためのGo用クライアントライブラリです。まず、pgxパッケージをプロジェクトにインストールします:
|
1 2 |
go get github.com/jackc/pgx/v5 |
次に、データベース接続を設定します。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
package main import ( "fmt" "github.com/jackc/pgx/v5" ) func connectDB(ctx context.Context) (*pgx.Conn, error) { connString := "postgres://username:password@localhost:5432/mydb?sslmode=disable" return pgx.Connect(ctx, connString) } |
このようにして、PostgreSQLとの接続が可能になります。
データベースマイグレーションの簡易例
データベースのテーブル構造を管理するためにマイグレーションを行うことは重要です。以下は簡単なSQL文を実行するコードです:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
conn, err := connectDB(context.Background()) if err != nil { log.Fatal("Unable to connect to database:", err) } _, err = conn.Exec(context.Background(), ` CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE NOT NULL ) `) |
これで、usersテーブルがなければ自動的に作成されます。
モデルとRepository層の分離設計
GinとPostgreSQLを連携させる際には、モデル(データ構造)とリポジトリ(DB操作)を分離することが推奨されます。以下はその例です:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
// model/user.go type User struct { ID int Name string Email string } // repository/user_repo.go func CreateUser(conn *pgx.Conn, user User) error { // ユーザーを作成する処理 } |
このようにすることで、コードの再利用性や保守性が向上します。
JSONレスポンスの型安全な処理方法
Ginは、JSON形式でのリクエストとレスポンスを扱う際、構造体(struct)を自動的にJSONに変換する機能を持っています。この仕組みを利用して、型安全で効率的なAPI開発が可能です。
structタグによるJSON変換
Go言語ではjsonタグを用いて、構造体のフィールドをJSONにマッピングできます。以下はその例です:
|
1 2 3 4 5 6 |
type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"` } |
このようにすることで、User構造体のフィールドがJSONに変換される際に「id」「name」「email」という名前で出力されます。
GinのContext Bindメソッド活用
リクエストデータを構造体に自動的にバインドするには、GinのBindJSONメソッドが役立ちます。以下はGETリクエストでの例です:
|
1 2 3 4 5 6 7 8 9 |
func createUser(c *gin.Context) { var user User if err := c.BindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"}) return } // ユーザーを作成する処理 } |
このようにして、リクエストボディからユーザー情報を自動的に取得できます。
カスタムバリデータの実装
Ginではbindingパッケージを使用することで、リクエストデータに対するカスタムバリデーションを実現できます。以下はその例です:
|
1 2 3 4 5 |
func validateEmail(email string) bool { // エラーチェック用関数(簡略版) return strings.Contains(email, "@") } |
このようにして、リクエストデータに不正な値が含まれている場合に適切に対処できます。
認証機能の実装例(JWTなど)
認証はセキュリティを強化するため非常に重要です。以下では、JWT(JSON Web Token)を使った認証機能の実装方法を紹介します。
トークン発行処理の実装
ユーザーがログイン時に発行されるトークンは、golang-jwt/jwtというライブラリを使用して作成できます。以下はその例です:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import ( "github.com/golang-jwt/jwt/v5" ) type Claims struct { Username string `json:"username"` jwt.StandardClaims } func generateToken(username string) (string, error) { secretKey := []byte("your-secret-key") token := jwt.NewWithClaims(jwt.SigningMethodHS256, Claims{ Username: username, StandardClaims: jwt.StandardClaims{ ExpiresAt: time.Now().Add(time.Hour * 1).Unix(), }, }) return token.SignedString(secretKey) } |
このようにして、トークンが発行され、ユーザーに提供されます。
ミドルウェアによるアクセス制御
JWTを用いることで、特定のエンドポイントにアクセスできるようにするミドルウェアを作成できます。以下はその例です:
|
1 2 3 4 5 6 7 8 9 10 |
func AuthMiddleware(c *gin.Context) { tokenString := c.GetHeader("Authorization") if tokenString == "" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Missing token"}) return } // トークンの検証処理... } |
このようにして、セキュリティを強化できます。
テストコードの書き方(httptest使用)
Ginではhttp/httptestパッケージを使用してAPIテストが可能です。以下はその実装例です。
単体テスト環境のセットアップ
単体テストでは、Ginサーバーを立ち上げずにMockサーバーを作成します:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
func TestGetUser(t *testing.T) { r := gin.Default() r.GET("/user", func(c *gin.Context) { c.JSON(200, gin.H{"id": 1, "name": "Alice"}) }) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/user", nil) r.ServeHTTP(w, req) if w.Code != 200 { t.Errorf("Expected status code 200, got %d", w.Code) } } |
このようにして、APIの応答をテストできます。
モックデータベースとの連携方法
テスト時にモックデータベースを使用する場合、pgxライブラリでモックDBを作成します:
|
1 2 3 4 5 |
func TestCreateUser(t *testing.T) { conn, _ := pgx.Connect(context.Background(), "mock") // 以下にモックデータベースとの連携処理を記述 } |
このようにして、テスト環境と本番環境を分離できます。
カバレッジ測定の実践
カバレッジを確認するにはgo test -coverコマンドを使用します:
|
1 2 |
go test -cover ./... |
これにより、どの部分がテストされていないかがわかります。定期的に実施することで、コード品質を向上させることができます。