🦫
【Golang】と【PostgreSQL】で始めるバックエンドAPI開発入門
Golangとは
Go言語(一般的に「Golang」とも呼ばれます)は、Googleによって開発されたオープンソースのプログラミング言語です。2009年にリリースされ、シンプルさ、高速なコンパイル速度、効率的な並行処理のサポートを特徴としています。
主な特徴:
- シンプルな文法: 学習が容易で、コードの読みやすさと保守性を高めます。
- 高速なパフォーマンス: コンパイルされたバイナリは高速に実行され、リソースの効率的な使用を可能にします。
- 並行処理のサポート: ゴルーチンとチャネルを使用して、シンプルかつ効率的に並行処理を実装できます。
- 強力な標準ライブラリ: ネットワーク、ファイルシステム、暗号化など、多くの機能を標準でサポートしています。
完成後のイメージ
- RESTful APIエンドポイント(ユーザー管理)
- PostgreSQLデータベース
- pgAdmin(データベース管理ツール)
- Dockerによる環境のコンテナ化
前提条件
以下のツールをインストールしておく必要があります:
- Docker Desktop
- Mac: Docker Desktop for Mac
- Windows: Docker Desktop for Windows
※Goのローカルインストールは不要です(Dockerコンテナ内で実行するため)
プロジェクトのセットアップ
1. プロジェクトの作成
mkdir my-go-api
cd my-go-api
2. 必要なファイルの作成
プロジェクトには以下のファイルが必要です:
my-go-api/
├── docker-compose.yml
├── Dockerfile
├── init.sql
├── .env
├── go.mod
└── main.go
環境構築
1. 環境変数の設定(.env)
# Application
APP_NAME=scholapod
# Database
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=testdb
DB_PORT=5432
# pgAdmin
PGADMIN_DEFAULT_EMAIL=admin@example.com
PGADMIN_DEFAULT_PASSWORD=adminpassword
PGADMIN_PORT=5050
2. Dockerfileの作成
FROM golang:1.21-alpine
WORKDIR /app
# ビルドに必要なパッケージのインストール
RUN apk add --no-cache git
# 依存関係のコピーとダウンロード
COPY go.mod .
# 依存関係の初期化とダウンロード
RUN go mod download
RUN go mod tidy
# ソースコードのコピー
COPY . .
# アプリケーションのビルド
RUN go build -o main .
# アプリケーションの実行
CMD ["./main"]
3. Docker Composeの設定
services:
app:
build: .
ports:
- "8080:8080"
depends_on:
db:
condition: service_healthy
environment:
- DB_HOST=db
- DB_USER=${POSTGRES_USER}
- DB_PASSWORD=${POSTGRES_PASSWORD}
- DB_NAME=${POSTGRES_DB}
- DB_PORT=${DB_PORT}
env_file:
- .env
db:
image: postgres:14
container_name: db_${APP_NAME}
ports:
- "5433:5432"
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
env_file:
- .env
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 5s
timeout: 5s
retries: 5
pgadmin:
image: dpage/pgadmin4
container_name: pgadmin_${APP_NAME}
environment:
- PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL}
- PGADMIN_DEFAULT_PASSWORD=${PGADMIN_DEFAULT_PASSWORD}
env_file:
- .env
ports:
- "${PGADMIN_PORT}:80"
depends_on:
- db
volumes:
- pgadmin_data:/var/lib/pgadmin
volumes:
postgres_data:
name: ${APP_NAME}_postgres_data
pgadmin_data:
name: ${APP_NAME}_pgadmin_data
4. データベーステーブルの定義(init.sql)
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE
);
APIの実装
1. Go Modulesの初期化(go.mod)
module my-go-api
go 1.21
require (
github.com/gorilla/mux v1.8.1
github.com/lib/pq v1.10.9
)
2. メインアプリケーションの実装(main.go)
package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
_ "github.com/lib/pq"
"github.com/gorilla/mux"
)
// User モデル
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
// データベース接続情報
func getDB() (*sql.DB, error) {
dbHost := os.Getenv("DB_HOST")
dbUser := os.Getenv("DB_USER")
dbPassword := os.Getenv("DB_PASSWORD")
dbName := os.Getenv("DB_NAME")
dbPort := os.Getenv("DB_PORT")
connStr := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
dbHost, dbPort, dbUser, dbPassword, dbName)
return sql.Open("postgres", connStr)
}
// ハンドラー関数
func createUser(w http.ResponseWriter, r *http.Request) {
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
db, err := getDB()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer db.Close()
query := `INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id`
err = db.QueryRow(query, user.Name, user.Email).Scan(&user.ID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(user)
}
func main() {
// ルーターの初期化
r := mux.NewRouter()
// ルートの設定
r.HandleFunc("/users", createUser).Methods("POST")
// サーバーの起動
log.Printf("Server starting on port 8080...")
log.Fatal(http.ListenAndServe(":8080", r))
}
動作確認方法
1. システムの起動
docker-compose up --build
2. APIの動作確認
# ユーザー作成のテスト
curl -X POST \
http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"name":"山田太郎","email":"yamada@example.com"}'
3. pgAdminでのデータベース確認
-
ブラウザで
http://localhost:5050
にアクセス
-
ログイン情報:
- Email: PGADMIN_DEFAULT_EMAIL(.envより)
- Password: PGADMIN_DEFAULT_PASSWORD(.envより)
-
新しいサーバー接続の設定:
- メニュー: サーバーグループを右クリック → "Register" → "Server..."
- "General"タブ:
- Name:
Scholapod DB
- Name:
- "Connection"タブ:
- Host:
db
- Port:
5432
- Database:
testdb
- Username:
postgres
- Password:
postgres
- Host:
4. データベースの直接確認
# データベースコンテナに接続
docker-compose exec db psql -U postgres -d testdb
# よく使うpsqlコマンド:
\dt -- テーブル一覧の表示
\d users -- usersテーブルの構造確認
\q -- psqlの終了
トラブルシューティング
1. ポートが既に使用されている場合
エラーメッセージ: Error response from daemon: Ports are not available
解決方法:
# 使用中のポートを確認
lsof -i :5432 # または該当のポート
# 既存のプロセスを停止
sudo service postgresql stop # PostgreSQLの場合
2. データベース接続エラー
-
環境変数の確認:
- .envファイルの設定が正しいか
- docker-compose.ymlでの環境変数の参照が正しいか
-
ネットワーク設定の確認:
docker network ls
docker network inspect my-go-api_default
3. コンテナの状態確認
# コンテナの状態確認
docker-compose ps
# ログの確認
docker-compose logs app # アプリケーションのログ
docker-compose logs db # データベースのログ
docker-compose logs pgadmin # pgAdminのログ
Discussion