
バックエンド開発には決まりきったコードがつきものだ。特にデータベースのクエリやAPIサーバーの周りで顕著になる。そうしたコードを手で書くのは時間がかかるし、間違いも起きやすい。コード生成ツール(codegen)なら、宣言的な仕様から型安全なGoコードを自動で作ってくれる。メンテナンスの手間も省ける。
この記事では2つのツールを紹介する。
sqlc は .sql ファイルを読み込み、型付きのパラメータと結果でクエリを実行するGo関数を生成する。
sqlc.yaml で入力と出力を設定する。sqlc generate を実行する。users テーブルがあるとしよう。
-- schema.sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
);メールアドレスでユーザーを引くクエリは次の通り。
-- queries.sql
-- name: GetUserByEmail :one
SELECT id, name, email FROM users WHERE email = $1;sqlc.yaml の設定。
version: "1"
packages:
- name: "db"
path: "./db"
queries: "./queries.sql"
schema: "./schema.sql"
engine: "postgresql"実行する。
sqlc generateするとこういうメソッドが生成される。
func (q *Queries) GetUserByEmail(ctx context.Context, email string) (User, error)バックエンドではこう使う。
user, err := dbQueries.GetUserByEmail(ctx, "alice@example.com")
if err != nil {
// handle error
}
fmt.Println("User:", user.Name)SQL文字列を手で組み立てたり行を走査したりする作業が消える。コードはよりきれいで安全になる。
oapi-codegen は OpenAPI の仕様から Go のサーバーコードとクライアントコードを生成する。インターフェースとリクエスト・レスポンスの型を作ってくれる。残るのはビジネスロジックの実装だけ。
oapi-codegen を実行する。小さな OpenAPI の仕様 api.yaml を用意する。
openapi: 3.0.0
info:
title: User API
version: 1.0.0
paths:
/users/{email}:
get:
summary: Get user by email
parameters:
- name: email
in: path
required: true
schema:
type: string
responses:
"200":
description: User found
content:
application/json:
schema:
$ref: "#/components/schemas/User"
"404":
description: User not found
components:
schemas:
User:
type: object
properties:
id:
type: integer
name:
type: string
email:
type: stringサーバーコードを生成する。
oapi-codegen -generate types,server -package api -o api.gen.go api.yamlこれでリクエスト・レスポンスの型(User struct)と、メソッドを持つ ServerInterface が生成される。
GetUsersEmail(ctx context.Context, email string) (api.User, error)インターフェースを実装する。
type ServerImpl struct {
db *db.Queries
}
func (s *ServerImpl) GetUsersEmail(ctx context.Context, email string) (api.User, error) {
user, err := s.db.GetUserByEmail(ctx, email)
if err != nil {
return api.User{}, err
}
return api.User{
Id: int64(user.ID),
Name: user.Name,
Email: user.Email,
}, nil
}サーバーをつなぐ。
router := api.NewRouter(&ServerImpl{db: dbQueries})
http.ListenAndServe(":8080", router)sqlc と oapi-codegen を一緒に使えば、Go のバックエンドでデータベースアクセスと API サーバーのコードを自動化できる。書くボイラープレートが減り、実行時のエラーも減る。集中すべきはアプリケーションの中心となるロジックだ。
© Melvin Laplanche - All rights reserved.