Goプロジェクトをレイアウトする賢明な方法は何ですか[終了]


113

より複雑になり始めているgoプロジェクトがあり、痛みを軽減するような方法でファイルシステムをレイアウトしたいと考えています。

意味のあるものの良い例はありますか?

回答:


132

2013年5月更新:公式ドキュメントは「コード編成」セクションにあります

Goコードはワークスペース内に保持する必要があります
ワークスペースは、ルートに3つのディレクトリがあるディレクトリ階層です。

  • src パッケージに編成されたGoソースファイルが含まれています(ディレクトリごとに1つのパッケージ)。
  • pkg パッケージオブジェクトを含み、
  • bin 実行可能なコマンドが含まれています。

go toolソースパッケージを構築し、その結果得られるバイナリをインストールpkgし、binディレクトリ。

srcサブディレクトリは、典型的には、1つ以上のソースパッケージの開発を追跡する(例えばGitのまたはMercurialのためのような)複数のバージョン管理リポジトリを含んでいます。

bin/
    streak                         # command executable
    todo                           # command executable
pkg/
    linux_amd64/
        code.google.com/p/goauth2/
            oauth.a                # package object
        github.com/nf/todo/
            task.a                 # package object
src/
    code.google.com/p/goauth2/
        .hg/                       # mercurial repository metadata
        oauth/
            oauth.go               # package source
            oauth_test.go          # test source

2014年7月の更新:Ben JohnsonのStructuring Applications in Go」を参照してください。

その記事には、次のようなヒントが含まれています。

アプリケーションからバイナリを分離する

main.go同じパッケージでファイルとアプリケーションロジックを組み合わせると、2つの影響があります。

  • アプリケーションがライブラリとして使用できなくなります。
  • アプリケーションバイナリは1つしか持てません。

これを修正するために見つけた最良の方法cmdは、プロジェクトの「」ディレクトリを使用することです。この場合、そのサブディレクトリはそれぞれアプリケーションバイナリです。

camlistore/
  cmd/
    camget/
      main.go
    cammount/
      main.go
    camput/
      main.go
    camtool/
      main.go

ライブラリ駆動開発

main.goルートからファイルを移動すると、ライブラリの観点からアプリケーションを構築できます。アプリケーションのバイナリは、単にアプリケーションのライブラリのクライアントです。

複数のバイナリを作成するために、ユーザーが複数の方法で対話することを望む場合があります。
たとえば、adderユーザーが数字を一緒に追加できる「」パッケージがある場合、Webバージョンだけでなくコマンドラインバージョンもリリースできます。
これを行うには、次のようにプロジェクトを整理します。

adder/
  adder.go
  cmd/
    adder/
      main.go
    adder-server/
      main.go

ユーザーは省略記号を使用して、「追加」アプリケーションバイナリを「取得」してインストールできます。

$ go get github.com/benbjohnson/adder/...

これで、ユーザーに「adder」と「adder-server」がインストールされました。

サブパッケージに夢中になるな

通常、私のプロジェクトのタイプはすべて非常に関連しているので、使いやすさとAPIの観点からはよりよく適合します。
これらのタイプは、それらの間でエクスポートされていない呼び出しを利用して、APIを小さく明確に保つこともできます。

  1. 関連するタイプとコードを各ファイルにまとめます。タイプと関数が適切に構成されている場合、ファイルのSLOCは200から500になる傾向があります。これは多くのように聞こえるかもしれませんが、ナビゲートするのは簡単です。1000 SLOCは通常、単一ファイルの上限です。
  2. 最も重要なタイプをファイルの上部に整理し、ファイルの下部に向かって重要度の低いタイプを追加します。
  3. アプリケーションが10,000 SLOCを超え始めたら、それを小さなプロジェクトに分割できるかどうかを真剣に評価する必要があります。

注:最後の練習が常に良いとは限りません:

申し訳ありませんが、私はこの慣習に同意できません。
タイプをファイルに分離することで、コード管理、可読性、保守性、テスト性が向上します。
また、単一の責任とオープン/クローズの原則に従うことも保証します…
します。循環依存を許可しないルールは、パッケージの明確な構造を強制することです。


(2013年2月の代替案についてsrcのみ)
GitHubコードのレイアウト」に示されているクラシックなレイアウトを見つけることができます」に。

アプリと両方のライブラリは、それぞれ独自のリポジトリにあるGithubにあります。
$GOPATHはプロジェクトのルートです。Githubリポジトリはそれぞれ、以下のいくつかのフォルダからチェックアウトされます$GOPATH

コードレイアウトは次のようになります。

$GOPATH/
    src/
        github.com/
            jmcvetta/
                useless/
                    .git/
                    useless.go
                    useless_test.go
                    README.md
                uselessd/
                    .git/
                    uselessd.go
                    uselessd_test.go
                    README.md

下の各フォルダ src/github.com/jmcvetta/は、個別のgitチェックアウトのルートです。

しかし、このredditページでは、いくつかの批判が寄せられました。

go getGoの最も便利な機能の1つである「」が壊れるので、レポをあなたが持っている方法で構築しないことを強くお勧めします。
Goを知っている人のためにコードを書く方がはるかに良いです。なぜなら、Goをコンパイルする人である可能性が最も高いからです。
そして、そうでない人のために、彼らは少なくとも言語を感じるでしょう。

メインパッケージをリポジトリのルートに配置します。
アセットをサブディレクトリに配置します(物事をきれいに保つため)。
コードの主要部分をサブパッケージに保存します(誰かがバイナリの外で再利用したい場合に備えて)。
見つけやすいように、リポジトリのルートにセットアップスクリプトを含めます。

それでも、ダウンロード、ビルド、インストール、およびセットアップの2つのステップのみのプロセスです。:

  • " go get <your repo path>":アセットのサブディレクトリを使用して、goコードをダウンロードしてインストールします
  • $GOPATH/<your repo path>/setup.sh:アセットを適切な場所に配布し、サービスをインストールします

15
大きな(大きな)問題の1つsetup.shは、Goが適度にクロスプラットフォームであるのに対し、POSIXシェルスクリプトはそうではないことです。
kostix 2013

jmcvetta構造はなりません取りに行く... / uselessdの両方がインストールされます取りに行く、無用uselessd輸入するので、取りに行く破ります。しかし、uselessが特にuselessd用に作成されたライブラリである場合は、サブフォルダーまたは兄弟として単一のgitリポジトリに保存する方が理にかなっていることに同意します。
mna

@PuerkitoBio同意する。バージョン管理とコンポーネントベースの管理(stackoverflow.com/a/933735/6309)に関する私のトレーニングは、リポジトリごとに1つのコンポーネントに向かっているため、この回答の2番目の部分に進みます。
VonC 2013

7

「プロジェクト」とは、Goパッケージではなく、開発したソフトウェアを意味すると思います。そうでなければ、ここここで助けを得ることができます。ただし、Go用のパッケージの作成とそれほど変わりません。パッケージを使用し、各パッケージ用のフォルダーを作成し、それらのパッケージをアプリケーションで組み合わせます。

自分で意見を述べるには、githubでトレンドのGoリポジトリを確認できます:https : //github.com/trending/go。注目すべき例は、ケイリーゼウスですです。

最も人気のあるスキームは、メインのGoファイルと多くのモジュールとサブモジュールを独自のディレクトリに置くことです。多くのメタファイル(ドキュメント、ライセンス、テンプレートなど)がある場合は、ソースコードをサブディレクトリに配置することをお勧めします。それは私が今までやったことです。


@aussiegeek、私はGoのエキスパートではありませんが、nemoが自分のコードで提案したものをうまく適用しました-アイデアは、プロジェクトディレクトリの下にモジュールを置くことができ、完全なプレフィックスを使用してそれらを参照する必要があるだけです-相対へ$GOPATH/srcたり、使用してgo get-table名前を。
kostix 2013

doozerdテストが弱いとしても、良い例ではありません。
イナンクムス

@InancGumusより良い例を提案することをお勧めします。
nemo 2017

これこれを見てください。
イナンクムス

1

Goツールで最適に動作し、ソース管理システムをサポートするようにコードをレイアウトする方法を定義する、Golangの作者による推奨アプローチがあります。


1
これ$GOROOTは、src/<project>ディレクトリ内のコードではなく、レイアウト方法です。
docwhat 2016年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.