はじめに
Go言語でAPIを構築する際に、手動でコードを書くのは手間がかかるだけでなく、エラーが発生しやすくなります。そこで、OpenAPI仕様を活用し、自動でコードを生成する方法を解説します。本記事では、oapi-codegenを使用して、Goコードを自動生成する手順を丁寧に説明します。
oapi-codegenとは?
oapi-codegenは、OpenAPI 3.0仕様に基づいてGoコードを自動生成するツールです。以下のような機能をサポートしています:
- APIモデルの生成
- Ginベースのサーバーコード生成
- クライアントコードの生成
- OpenAPI仕様を埋め込むコード生成
前提条件
- Goがインストールされている
- oapi-codegenのインストール済み
以下のコマンドでoapi-codegen
をインストールできます:
go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest
以下のコマンドでバージョンが出力されるか確認する
$ oapi-codegen -version
もし、
zsh: command not found: oapi-codegen
になった場合は、パスを通す。
go-api-newspaper % go env | grep PATH
# => GOPATH='/Users/jima/go'
go-api-newspaper %ls /Users/jima/go/bin
# => gopls oapi-codegen staticcheck
go-api-newspaper % export PATH=$PATH:/Users/jima/go/bin
go-api-newspaper % echo 'export PATH=$PATH:/Users/jima/go/bin' >> ~/.zshrc
go-api-newspaper % source ~/.zshrc
go-api-newspaper % oapi-codegen -version
# => github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen
# => v2.4.1
OpenAPI仕様のYAMLファイルを作成する
以下は、本記事で使用するサンプルのOpenAPI仕様です。このファイルをopenapi.yaml
として保存してください。
openapi.yaml
openapi: 3.0.3
info:
title: Go API Template # APIの名称。新聞管理用のテンプレートを定義。
version: 1.0.0 # APIのバージョン。メジャー、マイナー、パッチ番号で管理。
servers:
- url: http://0.0.0.0:8080/api/v1 # Dockerや他の環境でAPIをテストする際のベースURL。
- url: http://localhost:8080/api/v1 # ローカルホストでの開発時に使用。
- url: http://127.0.0.1:8080/api/v1 # ループバックアドレスを使用する場合のURL。
paths:
/newspaper:
post:
summary: Create a new newspaper # 新聞記事を新規作成するエンドポイント。
operationId: createNewspaper # 操作を一意に識別するID。
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/NewspaperCreateRequest' # 新規作成に必要なデータの構造を参照。
required: true # リクエストボディが必須であることを指定。
responses:
'201':
description: Created # リソースが正常に作成された場合のレスポンス。
content:
application/json:
schema:
$ref: '#/components/schemas/NewspaperResponse' # 作成された新聞データのレスポンス構造。
'400':
description: Bad Request # 入力データが不正だった場合のレスポンス。
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse' # エラー情報の構造を参照。
/newspaper/{id}:
get:
summary: Find newspaper by ID # IDで新聞記事を取得するエンドポイント。
operationId: getNewspaperById
parameters:
- name: id
in: path
required: true # パスパラメータが必須であることを指定。
schema:
type: integer # IDは整数型。
responses:
'200':
description: OK # 正常にデータが取得された場合。
content:
application/json:
schema:
$ref: '#/components/schemas/NewspaperResponse'
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not Found # 指定されたIDの新聞記事が見つからない場合。
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
patch:
summary: Update a newspaper by ID # IDで新聞記事を更新するエンドポイント。
operationId: updateNewspaperById
parameters:
- name: id
in: path
required: true
schema:
type: integer
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/NewspaperUpdateRequest' # 更新データの構造を参照。
required: true
responses:
'200':
description: Updated # 更新成功時のレスポンス。
content:
application/json:
schema:
$ref: '#/components/schemas/NewspaperResponse'
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
summary: Delete a newspaper by ID # IDで新聞記事を削除するエンドポイント。
operationId: deleteNewspaperById
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'204':
description: No Content # 成功した場合、コンテンツなしのレスポンスを返す。
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
schemas:
NewspaperResponse:
type: object
properties:
id:
type: integer # 新聞記事の一意の識別子。
title:
type: string # 新聞記事のタイトル。
columnName:
type: string # コラム名を指定。
required:
- id
- title
- columnName
NewspaperUpdateRequest:
type: object
properties:
title:
type: string # 更新対象のタイトル。
columnName:
type: string # 更新対象のコラム名。
NewspaperCreateRequest:
type: object
properties:
title:
type: string # 作成時に必要な新聞記事のタイトル。
columnName:
type: string # 作成時に必要なコラム名。
required:
- title
- columnName
ErrorResponse:
type: object
properties:
message:
type: string # エラーに関する詳細な説明を含む文字列。
required:
- message # エラーメッセージは必須プロパティ。
oapi-codegenでコードを生成する
oapi-codegenの設定を記載したconfig.yaml
を作成します:
config.yaml
package: api # 生成されるコードのパッケージ名
generate:
models: true # モデルコードの生成
gin-server: true # Gin用サーバーコードの生成
client: true # クライアントコードの生成
embedded-spec: true # OpenAPI仕様を埋め込む
output: api/api.gen.go # 生成されるコードの出力先
そして、以下のコマンドを実行します。
oapi-codegen --config=./config.yaml ./openapi.yaml
このコマンドを実行すると、api.gen.go
というファイルが自動生成されます。
生成されたコードの確認
api.gen.go
には、以下のようなコードが生成されます:
- リクエスト/レスポンス用のモデル
- Ginベースのエンドポイントハンドラ
- クライアントコード
まとめ
本記事では、oapi-codegen
を使用して、GoのAPIコードを効率的に生成する方法を解説しました。コード生成により、開発スピードの向上やバグの削減が期待できます。ぜひ、実際のプロジェクトで活用してみてください!