Golangにおけるプロジェクトのレイアウトについて
僕がGolangを好きな理由はいくつかあるが、主なものは
- コードが皆フォーマッターによって大体綺麗になる
- 言語機能が充実しすぎていないので処理が追いやすい(コーディングする時不便に感じることもあるが、チームでの開発においては読まれる方を重視したほうが良い)
- サードパーティのライブラリの導入が非常に簡単(もちろんプロジェクトに導入するときは慎重に行うべき)
そんなGoだけど、プロジェクトを作る時にどうパッケージを切っていくか。これが以外と暗黙の了解みたいな感じになっている気がする。
APIであればMVCライクに切るか、最近だとクリーンアーキテクチャが自分の流行だ。
CLIツールやライブラリだとプロジェクトのルート直下にフラットにファイルが展開されているものもある。
ということで少し気になったのでGoでプロジェクトを作る時にデファクトとなるようなパッケージレイアウトはあるのか?もし、あるとしたらどういう風に切るのかを少し調べてみた。
まず golang project layout
みたいな感じでググるとこのリポジトリが先頭にあがった。
GitHub - golang-standards/project-layout: Standard Go Project Layout
スターは4000近くもある。それなりに認知度が高いらしい。
READMEにはこのようにかかれている
これはGoアプリケーションプロジェクトの基本レイアウトです。 Goデベロッパーチームが定義した公式の標準ではありません。 ただ、このリポジトリの構成はGoエコシステムにおける共通の歴史的かつ新しいプロジェクトレイアウトパターンのセットです。 この切り方は、他のパターンよりも人気があります。 この構成ではいくつかの小さな拡張機能と、十分な大きさのプロダクションレベルでのアプリケーションに共通するいくつかのサポートディレクトリを備えています。
とのこと。確かにこの構成はよく見るような気がする。特にinternalパッケージとpkgパッケージは他のライブラリやツールでも頻繁に登場する。
READMEにはそれぞれこのように注釈されている
internal
内部でのみ使われるアプリケーションとライブラリコード。 これは、他の人のアプリケーションやライブラリでインポートさせたくないコードです。
/ internal / pkgディレクトリ(例:/ internal / pkg / myprivlib)に、実際のアプリケーションコードを書いて、/ internal / appディレクトリ(/ internal / app / myapp)で更に共有される。
共有の部分がいまいちピンと来ないけど、コアのコードやヘルパー的なコードはこの中で書こうということなのだろう。
pkg
外部アプリケーション(たとえば、/ pkg / mypubliclib)で使用できるライブラリコード。 他のプロジェクトは、pkg内のコードが動作することを期待してパッケージwpインポートするので、ここに何かを入れる前にしっかり考えてください:-)
また、ルートディレクトリに多くの非Goコンポーネントとディレクトリが含まれていて、GopherCon EU 2018のインダストリアルプログラミングのベストプラクティスに記載されているように、さまざまなGoツールを簡単に実行できるように、Goコードを1か所にグループ化する方法です。
このプロジェクトレイアウトパターンを使用している人気のあるGoリポジトリを確認するには、/ pkgディレクトリを参照してください。 これは一般的なレイアウトパターンですが、普遍的に受け入れられているわけではなく、Goコミュニティの一部では推奨していません。
ふむふむ。基本的に外部で利用する時はこのpkgディレクトリが参照されることが多いということか。 試しにこの構成に心当たりのあるプロジェクトをいくつか挙げてみようと思う。
僕もよくお世話になっているkubernetesは今回のstandard repositoryに近い構成だ。internalパッケージはないが pkg
, cmd
, api
等他のツールでもよく見るような構成になっている。
次は、、、といきたいとこだったんだけど、以外にもgo-awesome経由でリポジトリを漁っているとpkgディレクトリはあるけどinternalはない。みたいなケースが多くて探すのが疲れた。
go-awesomeに入っているツールやライブラリの構成を眺めていて思ったのはフラットな構成がかなり多いってことだ。勿論小さなプロジェクトであればそれでいいしわかりやすいから全然いいと思う。
他の大きなプロジェクトも名称等は違えど、役割として共通しているのだろうなっていうディレクトリが多かった気がする。
ちなみに英語であれば今回のプロジェクトのレイアウトについて論じているブログ等はある
どっちも挙げている構成は最初に挙げたリポジトリと共通点が多い。ただ、Golangの公式からガイドライン等が発表されていないのであくまで全て非公式なものではある。 僕個人としては他のプロジェクトのコードを少し追いたい時などはこういう風に共通点があると非常に楽なので助かる。
まとめ
- プロジェクトのレイアウトの切り方は大きなプロジェクトにおいては結構共通点が多い
- でも明確にレイアウトのガイドラインが決定されているわけではないので好きにやればいい