🐡

Go(v1.23.5)によるWeb API サーバーのローカル開発環境を構築する

2025/02/19に公開

はじめに

はじめまして、otot_devです。

Go の環境構築記事の 3 記事目で、↑の記事の続編として、ローカル開発環境を構築したので備忘録として記事を書きました。

概要

一般的に使用されるであろう、API サーバーのローカル環境を構築します。
Go の Web API サーバーと mariadb(MySQL)の構築します。

最終的なアウトプット

今回のコード一式は以下の URL にあります。

https://github.com/otoshimtoshi/go-docker-template/tree/v1.2.0

v1.1.0 からの全量差分は↓で確認できます。

https://github.com/otoshimtoshi/go-docker-template/compare/v1.1.0...v1.2.0

バージョン情報

  • go:v1.23.5
  • air-verse/air:v1.61.7
  • go-delve/delve: v1.24.0
  • gin-gonic/gin:v1.10.0
  • jinzhu/gorm:v1.9.16
  • joho/godotenv:v1.5.1
  • golang-migrate/migrate/v4:v4.18.2

一部のフレームワークやライブラリ紹介

gin-gonic/gin

(通称 Gin)は、Go により書かれた軽量で高速な Web フレームワークです。

主な特徴

  • 高速: net/http のラッパーであり、内部で Radix ツリーを使用した効率的なルーティングを採用
  • ミドルウェア: 認証、ロギング、エラーハンドリングなどを簡単に追加可能
  • JSON の扱いが簡単: リクエスト/レスポンスの JSON バインディングが直感的

シンプルな API サーバーを構築するのに適しているようです。

jinzhu/gorm

(通称 GORM)は、Go 言語向けの強力な O/R マッパ(Object-Relational Mapper)ライブラリです。

主な特徴

  • シンプルな API: Go の構造体を使ってデータベース操作が直感的にできる
  • リレーション管理: One-to-Many, Many-to-Many などの関連付けをサポート
  • トランザクション: Begin, Commit, Rollback で簡単に制御可能

SQL を直接書かずに Go の構造体を使ってデータベースを操作できるため、Go での Web 開発に広く使われています。

golangci/golangci-lint

Go 言語向けの高速で拡張性のある静的解析ツールです。

主な特徴

  • コード品質向上: コードのバグやスタイル違反を早期に発見
  • カスタマイズ可能: .golangci.yml で有効/無効にするルールを設定可能
  • CI/CD との統合: GitHub Actions や GitLab CI などに簡単に組み込み可能

Go プロジェクトの品質を維持するために、ほぼデファクトスタンダードとして使われています。

ディレクトリ構成

さっと Web API サーバーを構築したかったので、あまりアーキテクチャの構成は気にしせず作ってあります。詳細は Github のコードを見てください。

https://github.com/otoshimtoshi/go-docker-template

.
├── app
│   ├── constants
│   ├── domain
│   ├── infrastructure
│   ├── interfaces
│   │   ├── controllers
│   │   └── database
│   └── usecase
├── migrations
├── seeds
│   └── seeds
└── tests
    └── manual

主要ファイルの紹介

構成には記載がない主要なファイルを紹介したいと思います。

Dockerfile

Dockerfile は仮想環境を立ち上げるために必要な主要ファイルですね。

# v1.23.5
FROM golang:1.23-alpine

WORKDIR /app

# v1.61.7
RUN go install github.com/air-verse/air@latest
# v1.24.0
RUN go install github.com/go-delve/delve/cmd/dlv@latest

COPY go.mod go.sum ./
RUN go mod download

# v1.10.0
RUN go get github.com/gin-gonic/gin \
# v1.9.16
    github.com/jinzhu/gorm \
    github.com/jinzhu/gorm/dialects/mysql \
# v1.5.1
    github.com/joho/godotenv

# v4.18.2
RUN go install -tags 'mysql' github.com/golang-migrate/migrate/v4/cmd/migrate@latest

CMD ["air", "-c", ".air.toml"]

docker-compose.yml

Web API サーバーとして api コンテナ(go-api)、RDB として db コンテナ(go-db)を起動するように設定しています。

services:
  api:
    container_name: go-api
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8080:3000
      - 2345:2345 # リモートデバッグ用
    volumes:
      - ./:/app
    depends_on:
      - db
  db:
    container_name: go-db
    image: mariadb:10
    platform: linux/x86_64
    ports:
      - '3306:3306'
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: sample
      TZ: 'Asia/Tokyo'
    volumes:
      - sample-db:/var/lib/mysql

volumes:
  sample-db:
    driver: local

.air.toml

air はホットリロードするために必要です。
dockerでgoのホットリロード環境を爆速で構築するの記事でも書いたのですが、以下の air 起動時のコマンド設定をすることでホットリロードできます。go-apiコンテナのports → 2345:2345の設定も重要です。2345 ポートを起点として air を起動させています。

# Customize binary, can setup environment variables when run your app.
- full_bin = "APP_ENV=dev APP_USER=air ./tmp/main"
+ full_bin = "APP_ENV=dev APP_USER=air dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec --continue ./tmp/main"

.golangci.yml

Go 言語向けの高速で拡張性のある静的解析ツールです。これがあることにより、開発時のコード品質を一定に保つことができます。

linters:
  enable-all: true
  disable:
    - varnamelen # variable name 'x' is too short for the scope of its usage
    - forbidigo # use of `fmt.Printf` forbidden by pattern `^(fmt\.Print(|f|ln)|print|println)$`
    - godot # Comment should end in a period
    - nonamedreturns # named return "xxxx" with type "[]xxxx.xxxx" found
    - gosmopolitan # string literal contains rune in Han script
    - wsl # assignments should only be cuddled with other assignments
    - depguard # package "github.com/xxxx/xxxx" is not allowed
    - revive
    - stylecheck
    - predeclared
    - gofumpt
    - gci
    - exportloopref
  skip-dirs:
  # 羅列したディレクトリはlinterが実行されない
  #  -
  skip-files:
  # 羅列したファイルはlinterが実行されない
  #  -
linters-settings:
  # https://github.com/ldez/tagliatelle?tab=readme-ov-file#examples-1
  tagliatelle:
    case:
      rules:
        json: snake

.vscode/launch.json

VS code を使用している方限定にはなりますが、デバッグ実行する際に使用する launch.json ファイルです。

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Go Debug",
      "type": "go",
      "request": "attach",
      "mode": "remote",
      "port": 2345
    }
  ]
}

実際に動かしてみる

Docker

# バックグラウンド実行の場合
% docker compose up -d
# ログ出力あり実行の場合
% docker compose up

Go Modules

Go モジュールの依存関係を整理するコマンドです。

% go mod tidy

Database Migration

構築した db コンテナに対して、go-api コンテナからマイグレーションを実行し、その後、seed データの投入します。

% docker exec -it go-api sh
% migrate -database 'mysql://root:password@tcp(go-db:3306)/sample' -path migrations up
% migrate -database 'mysql://root:password@tcp(go-db:3306)/sample' -path migrations down
% go run seeds/seeder.go

Linting

Go プロジェクト内のコードを静的解析し、問題(バグ、非推奨な記述、コードスタイル違反、...etc)を確認します。

% golangci-lint run
% golangci-lint run --fix
GitHubで編集を提案

Discussion