Go 言語で API サーバーの開発をはじめるためのライブラリ選定

こんにちは、まちいろの工藤です。

まちいろでは開発フレームワークに Rails を採用していますが、最近の新規案件では Go 言語を採用してみています。この記事では、Go で開発を始めるにあたって行ったライブラリ選定の中身を紹介したいと思います。

選定にあたっては、awesome-go や Qiita などの記事を参考にしました。

Modules

Go 1.11 から Go modules が導入されたとのことで、素直に Go modules を利用することにしました。特にハマることもなく利用ができています。

Web Application Framework

gRPC + grpc-gateway or grpc-web

https://github.com/grpc/grpc-go
・🙆proto でスキーマ駆動開発が可能
・🙅‍♂️REST API を提供する場合は grpc-gateway/grpc-web のようなプロキシを挟む必要がある
・🙅‍♂️(gRPC の問題ではないが) gRPC 採用時のインフラ周りのノウハウが社内にまだ無い

protoc-gen-swagger + go-swagger

https://github.com/grpc-ecosystem/grpc-gateway/tree/master/protoc-gen-swagger
・🙆proto をベースに swagger 定義ファイルを生成し、go-swagger でコードを自動生成できる
・🙅‍♂️protoc-gen-swagger で一部 swagger の設定をサポートしていない項目があった
・🙅‍♂️protoc-gen-swagger のドキュメントが無く、直接 proto のスペックを調べながら定義方法を覚える必要がある
・以下の記事を参考にさせていただきました

go-swagger

https://github.com/go-swagger/go-swagger
・🙆swagger 定義ファイルからコードを自動生成できる
・🙅‍♂️swagger 定義ファイルの設定が煩雑で、冗長的になりやすい
・🙅‍♂️OpenAPI 3.0 はサポートされていない

goa

https://github.com/goadesign/goa
・🙆独自 DSL で定義したスキーマからコードの自動生成が可能
・🙅‍♂️Go 1.11 でコードの自動生成のパフォーマンスが悪い (Go 1.10 では問題なかった)

echo

https://github.com/labstack/echo
・🙆シンプル・高パフォーマンスの WAF
・🙆国内で採用事例が多く、情報が多い
・🙅‍♂️net/http をラップした API が提供されるので、例えば middleware の書き方が echo 向けになったりする
・🙅‍♂️スキーマ駆動で開発ができない

今回は要件がある程度決まっていたので、「スキーマ駆動で開発ができるか」「Web 向けの REST API の開発がしやすいか」を重要視し、go-swagger を採用することにしました。goa も検討したのですが、Go 1.11 ではコード生成にそこそこ時間がかかってしまい、そこで調査をやめてしまいました。

ORM

gorp

https://github.com/go-gorp/gorp
・🙆シンプルな API を提供
・🙅‍♂️SELECT 文は生 SQL を書くため、クエリビルダが別途必要

★gorm

https://github.com/jinzhu/gorm
・🙆ActiveRecord のような機能豊富な ORM
・🙆ドキュメントが充実しており、仕様の理解が容易

最初は gorp を使っていたのですが、生 SQL を書くのが段々と辛くなってきて gorm に切り替えました。Rails/ActiveRecord を経験している方にとっては、とっつきやすいライブラリだと思います。

DB Migration

goose

https://github.com/pressly/goose
・マイグレーションで調べると一番出てくるライブラリ
・🙅‍♂️現在は開発が停滞している?

★migrate

https://github.com/golang-migrate/migrate
・ActiveRecord の migration のようなライブラリ
・🙆CLI もあるが、Go コードから実行することもできる

sqldef

https://github.com/k0kubun/sqldef
・Ridgepole のようなライブラリ

goose が一番有名なようですが、ActiveRecord のマイグレーション方法に慣れているため、一旦 migrate で開発を進めています。

Configuration

★godotenv

https://github.com/joho/godotenv
・.env から環境変数をロードする

envconfig

https://github.com/kelseyhightower/envconfig
・環境変数を struct に展開する

godoenv と envconfig を使って、環境変数を格納する struct に展開しています。

Validation

★go-playground/validator

https://github.com/go-playground/validator
・Struct のタグを元にバリデーションを行う
・🙆独自のバリデーションを追加することが可能
・🙆複数のバリデーションを Alias としてまとめることが可能

★libphonenumber

https://github.com/ttacon/libphonenumber
・Google の libphonenumber の Go 実装
・電話番号のバリデーションに利用

go-playground/validator はとても便利なライブラリで、DB に永続化する Entity や、go-swagger から生成される HTTP Request Model に対するバリデーションに利用しています。

i18n

★go-i18n

https://github.com/nicksnyder/go-i18n

Logging

logrus

https://github.com/sirupsen/logrus
・採用事例が多い

★zap

https://github.com/uber-go/zap
・🙆高パフォーマンスなロギングライブラリ
・🙆一般的な Logger インターフェースを持つ SugarLogger を採用しても、それなりに高パフォーマンス

最初は logrus を使っていましたが、途中で zap の存在を知り乗り換えました。アクセスログ等を標準出力に吐き出す目的で利用しています。

Test

★ginkgo

https://github.com/onsi/ginkgo
・BDD テスティングフレームワーク

★gomega

https://github.com/onsi/gomega
・Ginkgo と合わせて使う Matcher ライブラリ

途中まで標準の test パッケージで頑張っていたのですが、テスト全体の見通しが悪いのと、BDD に慣れているというのがあり、ginkgo に切り替えました。RSpec に慣れている人であれば、特に迷うこと無く使えます。

Static file management

go-bindata

・🙅‍♂️既に削除されている

go-assets

https://github.com/jessevdk/go-assets

★statik

https://github.com/rakyll/statik

どれもできることは同じようですが、現在も開発が続いている statik を採用しました。

Unique ID Generator

uuid

https://github.com/satori/go.uuid
・UUID 実装

★ulid

https://github.com/oklog/ulid
・🙆ソート可能な UUID 互換実装

xid

https://github.com/rs/xid
・🙆ソート可能、かつ20文字と UUID より文字列が短い
・🙅‍♂️生成される文字列が推測しやすい

当初は xid を使っていたのですが、連続して生成すると文字列がほぼ同じになるため、ulid に切り替えました。

DI Container

★dig

https://github.com/uber-go/dig

最後に

本番導入はまだこれからなので利用するライブラリもまた変わってくると思いますが、一旦今利用しているものを書き出してみました。やはり WAF の選定が一番悩みましたが、go-swagger を使ってスキーマの恩恵を受けながら開発ができているのでとても満足しています。今度は go-swagger を使ってどういった開発を行っているかについても記事にしていきたいと思います。

これから Go で開発をしたい方の参考になれば幸いです。


<まちいろではエンジニアを絶賛募集中です!>


この記事が気に入ったらサポートをしてみませんか?