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 コードから実行することもできる
・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 で開発をしたい方の参考になれば幸いです。
<まちいろではエンジニアを絶賛募集中です!>