翻訳:
これは、Goアプリケーションプロジェクトの基本的なレイアウトです。これは、コアとなるGo開発チームによって定義された公式の標準ではありませんが、Goエコシステムの中で、歴史的に共通しているプロジェクトのレイアウトパターンのセットとなっています。これらのパターンの中には、他のパターンよりも人気のあるものもあります。また、現実世界の大規模なアプリケーションに共通するいくつかのサポートディレクトリに加えて、いくつかの小さな機能強化が行われています。
Goを学ぼうとしている場合や、自分でPoCやおもちゃのプロジェクトを構築しようとしている場合、このプロジェクトレイアウトはやりすぎです。最初は本当にシンプルなものから始めてください(main.go
ファイルが1つあれば十分です)。プロジェクトが大きくなるにつれて、コードが適切に構造化されているかどうかが重要になることに注意してください。そうしないと、多くの隠れた依存関係やグローバルな状態を持つ厄介なコードになってしまいます。プロジェクトで作業する人が増えれば、さらに多くの構造が必要になります。そこで、パッケージやライブラリを管理するための共通の方法を導入することが重要になります。オープンソースプロジェクトがある場合や、他のプロジェクトがプロジェクトリポジトリからコードをインポートしていることを知っている場合は、プライベートな(内部的な)パッケージやコードを持つことが重要になります。リポジトリをクローンして、必要なものだけを残し、他のものはすべて削除してください。リポジトリにあるからといって、すべてを使わなければならないわけではありません。これらのパターンはすべてのプロジェクトで使われているわけではありません。vendor
パターンでさえも、万能ではありません。
Go 1.14では、Go Modules
がついに本番に向けて準備が整いました。使用しない特別な理由がない限り、Go Modules
を使用してください。もし使用するのであれば、$GOPATH やプロジェクトをどこに置くかを気にする必要はありません。レポの基本的な go.mod
ファイルは、プロジェクトが GitHub でホストされていることを前提としていますが、必須ではありません。モジュールパスは何でも構いませんが、最初のモジュールパスコンポーネントの名前にはドットを付けてください (現在の Go のバージョンではもうこれを強制していませんが、少し古いバージョンを使っているのであれば、これを付けなくてもビルドが失敗しても驚かないでください)。これについて詳しく知りたい場合は、Issue 37554
と 32819
を参照してください。
このプロジェクトは意図的に一般的なレイアウトを使用しており、特定のGoパッケージを押し付けているわけではありません。
これはコミュニティの取り組みです。 新しいパターンが表示された場合、または既存のパターンの1つを更新する必要があると思われる場合は、issueで起票してください。
名前付け、フォーマット、スタイルについてサポートが必要な場合は、gofmt
とgolint
を実行することから始めます。また、次のGoコードスタイルのガイドラインと推奨事項も必ずお読みください:
- https://talks.golang.org/2014/names.slide
- https://golang.org/doc/effective_go.html#names
- https://blog.golang.org/package-names
- https://github.com/golang/go/wiki/CodeReviewComments
- Style guideline for Go packages (rakyll/JBD)
追加の背景情報については、Go Project Layout
を参照してください。
パッケージの命名と整理、およびその他のコード構造の推奨事項の詳細:
- GopherCon EU 2018: Peter Bourgon - Best Practices for Industrial Programming
- GopherCon Russia 2018: Ashley McNamara + Brian Ketelsen - Go best practices.
- GopherCon 2017: Edward Muller - Go Anti-Patterns
- GopherCon 2018: Kat Zien - How Do You Structure Your Go Apps
パッケージ指向の設計ガイドラインとアーキテクチャレイヤーに関する中国の投稿
このプロジェクトの主なアプリケーション。
各アプリケーションのディレクトリ名は、欲しい実行ファイルの名前と一致するようにしてください(例: /cmd/myapp
)。
アプリケーションディレクトリには多くのコードを入れないようにしましょう。コードをインポートして他のプロジェクトで使えると思うならば、/pkg
ディレクトリに置くべきです。コードが再利用できない場合や、他の人に再利用してほしくない場合は、そのコードを/internal
ディレクトリに置いてください。他の人が何をするか驚くでしょうから、自分の意図を明確にしてください。
このような場合は、/internal
ディレクトリと/pkg
ディレクトリからコードをインポートして呼び出す小さなメイン関数を持つのが一般的ですが、それ以外は何もしません。
例に関しては、/cmd
ディレクトリを参照してください。
プライベートなアプリケーションやライブラリのコード。これは、他の人が自分のアプリケーションやライブラリにインポートしたくないコードです。このレイアウトパターンは、Goコンパイラによって強制されることに注意してください。詳細については、Go 1.4のリリースノート
を参照してください。トップレベルの内部ディレクトリに限定されないことに注意してください。プロジェクトツリーのどのレベルでも、複数の内部ディレクトリを持つことができます。
オプションで、内部パッケージに少し余分な構造を追加して、共有内部コードと非共有内部コードを分離することができます。(特に小規模なプロジェクトでは) 必須ではありませんが、パッケージの使用目的を示す視覚的な手がかりがあるのは良いことです。実際のアプリケーションコードは /internal/app
ディレクトリ (例: /internal/app/myapp
) に、それらのアプリケーションで共有されるコードは /internal/pkg
ディレクトリ (例: /internal/pkg/myprivlib
) に置くことができます。
外部アプリケーションで使用しても問題ないライブラリコード(例: /pkg/mypubliclib
)。他のプロジェクトは、これらのライブラリが動作することを期待してインポートしますので、ここに何かを置く前によく考えてください :-)。内部ディレクトリは、プライベートパッケージがインポートできないようにするためのより良い方法であることに注意してください。/pkg
ディレクトリは、そのディレクトリにあるコードが他の人に使われても安全であることを明示的に伝える良い方法です。I'll take pkg over internal blog post by Travis Jeffery
は、pkg
ディレクトリと内部ディレクトリの概要と、それらを使用することが意味のある場合の概要を提供しています。
また、ルートディレクトリにGo以外のコンポーネントやディレクトリが多数含まれている場合は、Goコードを1つの場所にグループ化して、さまざまなGoツールを簡単に実行できるようにする方法でもあります(これらの講演で言及されているように:産業用プログラミングのベストプラクティス
from GopherCon EU 2018、GopherCon 2018:Kat Zien-How Do You Structure Your Go Apps
および GoLab 2018-Massimiliano Pippi-Goのプロジェクトレイアウトパターン
)。
このプロジェクトレイアウトパターンを使用している人気のある Go repos を見たい場合は /pkg
ディレクトリを参照してください。これは一般的なレイアウトパターンですが、普遍的に受け入れられているわけではありませんし、Goコミュニティの中には推奨していない人もいます。
アプリプロジェクトが非常に小さく、追加レベルのネストがあまり価値をもたらさない場合は、使用しないでください(本当に必要な場合を除く:-))。 それが十分に大きくなり、ルートディレクトリがかなり肥大化してきたときに考えてください(特に、Go以外のアプリコンポーネントがたくさんある場合)。
アプリケーションの依存関係 (手動で管理するか、新しい組み込みの Go Modules
機能のようなお気に入りの依存関係管理ツールで管理します)。go mod vendor
コマンドは、/vendor
ディレクトリを作成します。デフォルトでオンになっている Go 1.14 を使用していない場合は、go build
コマンドに -mod=vendor
フラグを追加する必要があるかもしれないことに注意してください。
ライブラリをビルドしている場合は、アプリケーションの依存関係をコミットしないでください。
1.13
以降、Go はモジュールプロキシ機能も有効にしています (デフォルトでは https://proxy.golang.org
をモジュールプロキシサーバとして使用しています)。この機能
についての詳細は、ここを読んで、あなたの要件や制約に適合するかどうかを確認してください。そうであれば、ベンダディレクトリは全く必要ありません。
OpenAPI/Swaggerの仕様、JSONスキーマファイル、プロトコル定義ファイル。
例に関しては、/api
ディレクトリを参照してください。
ウェブアプリケーション固有のコンポーネント:静的ウェブアセット、サーバーサイドテンプレート、SPA。
設定ファイルのテンプレートまたはデフォルトの設定。
confd
または consul-template
テンプレートファイルをここに置きます。
システムinit(systemd, upstart, sysv)とプロセスマネージャ/スーパーバイザ(runit, supervisord)の設定。
様々なビルド、インストール、解析などの操作を行うためのスクリプトです。
これらのスクリプトはルートレベルの Makefile を小さくシンプルに保ちます (例: https://github.com/hashicorp/terraform/blob/master/Makefile
)。
例に関しては、/scripts
ディレクトリを参照してください。
パッケージングと継続的インテグレーション。
クラウド (AMI)、コンテナ (Docker)、OS (deb、rpm、pkg) パッケージの設定とスクリプトを /build/package
ディレクトリに置きます。
CI (travis, circle, drone) の設定とスクリプトを /build/ci
ディレクトリに配置します。CIツールの中には(Travis CIなど)、設定ファイルの場所に非常にこだわるものがあることに注意してください。コンフィグファイルを /build/ci
ディレクトリに置き、CIツールが期待する場所にリンクしてみてください(可能であれば)。
IaaS、PaaS、システム、コンテナオーケストレーションのデプロイメント設定とテンプレート (docker-compose、kubernetes/helm、mesos、terraform、bosh)。
いくつかのリポジトリ (特に kubernetes でデプロイされたアプリ) では、このディレクトリは /deploy
と呼ばれていることに注意してください。
追加の外部テストアプリとテストデータ。/test
ディレクトリは自由に構成してください。大規模なプロジェクトでは、データのサブディレクトリを持つことは理にかなっています。例えば、/test/data
や /test/testdata
などのディレクトリが必要な場合、そのディレクトリにあるものを無視することができます。Go は "." や "_" で始まるディレクトリやファイルも無視するので、テストデータディレクトリの名前の付け方に柔軟性があることに注意してください。
例に関しては、/test
ディレクトリを参照してください。
デザインドキュメントとユーザードキュメント (godocで生成されたドキュメントに加えて)。
例に関しては、/docs
ディレクトリを参照してください。
このプロジェクトをサポートするツールです。これらのツールは /pkg
と /internal
ディレクトリからコードをインポートできることに注意してください。
例に関しては、/tools
ディレクトリを参照してください。
あなたのアプリケーション、またはpublic librariesのための例。
例に関しては、/examples
ディレクトリを参照してください。
外部ヘルパーツール、フォークされたコード、その他のサードパーティ製ユーティリティ(Swagger UIなど)。
Gitフック。
リポジトリに付随するその他のアセット(画像、ロゴなど)。
Githubページを使用していない場合は、プロジェクトのWebサイトのデータを置く場所です。
例に関しては、/website
ディレクトリを参照してください。
Goプロジェクトの中には src
フォルダを持っているものもありますが、これは通常、開発者が一般的なパターンであるJavaの世界から来た場合に起こります。可能であれば、このようなJavaのパターンを採用しないようにしてください。あなたのGoコードやGoプロジェクトがJavaのように見えることは本当に避けてください。
プロジェクトレベルの /src
ディレクトリと、Goコードの書き方
で説明されているように、Go がワークスペースに使用する /src
ディレクトリを混同しないようにしてください。環境変数 $GOPATH
は、(現在の)ワークスペースを指します (Windows 以外のシステムでは、デフォルトでは $HOME/go
を指します)。このワークスペースには、トップレベルの /pkg
, /bin
, /src
ディレクトリが含まれています。実際のプロジェクトは /src
の下のサブディレクトリになりますので、プロジェクト内に /src
ディレクトリがある場合、プロジェクトのパスは以下のようになります。/some/path/to/workspace/src/your_project/src/your_code.go
のようになります。Go 1.11 では、プロジェクトを GOPATH
の外に置くことができますが、このレイアウトパターンを使うのが良いというわけではないことに注意してください。
-
Go Report Card -
gofmt
,go vet
,gocyclo
,golint
,ineffassign
,license
,misspell
でコードをスキャンします。github.com/golang-standards/project-layout
をプロジェクトリファレンスに置き換えてください。 -
GoDoc - GoDocで作成したドキュメントのオンライン版を提供します。リンクを自分のプロジェクトへのリンクに変更してください。 -
Pkg.go.dev - Pkg.go.devは、囲碁の発見とドキュメントの新しい目的地です。バッジ生成ツールを使ってバッジを作成することができます。
-
リリース - あなたのプロジェクトの最新のリリース番号が表示されます。githubのリンクを変更して、あなたのプロジェクトを指すようにしてください。
サンプル/再利用可能なコンフィグ、スクリプト、コードを備えた、より意見の多いプロジェクトテンプレートはWIPです。