複数ファイルのGoプロジェクトの整理[終了]


237

注:この質問はこれと関連しいますが、Goの歴史では2年は非常に長い時間です。

開発中にGoプロジェクトを編成する標準的な方法は何ですか?

私のプロジェクトは単一のパッケージなmypackので、すべての.goファイルをmypackディレクトリに配置したと思います。

しかし、その後、開発中にテストしたいので、少なくともmainパッケージを宣言するファイルが必要です。これにより、go run trypack.go

これをどのように整理すればよいですか?やっgo install mypackてみたいと思うたびにやる必要がありますか?


14
この簡単なスクリーンキャストはすばらしいです:youtube.com/watch
Matt

これは、パッケージを使用してプロジェクトを整理する方法を理解するうえで役立つもう1つのリンクです。公式のGoコードの書き方よりもわかりやすいと思います。
IamNaN 2015

新しいGoモジュールシステムの場合、この回答はモジュール構造、モジュール内のパッケージの配置、単一のリポジトリに複数のモジュールを含めるかどうかなどをカバーします。最終的に、モジュールの公式の「Goコードの記述方法」の紹介ドキュメントが更新されます、しかしそれはまだ起こっていません。(Goが初めての場合やGoモジュールが初めての場合でも、モジュールのドキュメントの多くがGOPATHに精通していることを前提としているため、モジュールの詳細を読む前に、「Goコードの記述方法」のドキュメントを読む価値があります)。
通常182

回答:


171

Goコードの記述方法に関するこのページを確認することをお勧めします

go buildわかりやすい方法でプロジェクトを構成する方法と、テストを作成する方法の両方について説明します。テストは、mainパッケージを使用するcmdである必要はありません。それらは単に各パッケージの一部としてTestXという名前の関数にすることができ、go testそれらを検出します。

あなたの質問のそのリンクで提案されている構造は少し古くなっていますが、Go 1のリリースでは、のpkg下にディレクトリを配置する必要がなくなりましたsrc。仕様に関連する3つのディレクトリは、GOPATHのルートにある3つのみです:bin、pkg、src。srcのmypack下にプロジェクトを配置できます。その下に、mypack_test.goを含むすべての.goファイルがあります。

go build 次に、ルートレベルのpkgとbinにビルドします。

したがって、GOPATHは次のようになります。

~/projects/
    bin/
    pkg/
    src/
      mypack/
        foo.go
        bar.go
        mypack_test.go

export GOPATH=$HOME/projects

$ go build mypack
$ go test mypack

更新:> = Go 1.11以降、モジュールシステムはツールの標準的な部分になり、GOPATHの概念はほとんど廃止されています。


26
変数をエクスポートするときは、〜ではなく$ HOMEを使用してください。
Johan S

6
変数をエクスポートするときに$ HOMEが〜よりも推奨されるのはなぜですか?
425nesp 2014

8
〜は変数ではなく、単なるエイリアスです。
Pih 2014

6
@ 425nesp Johanは間違っています-間違っていません。シェルはさまざまですが、環境変数を設定するとbashが拡張され~、たとえばbusybox bourneシェルも拡張されます。自分で試してみてください:export BOB=~ && env | grep ^BOBBOB=/your/homedir
オースティンアダムス

1
$HOMEより多くのシェルで動作します。~たとえば、fish
ホジュイ

60

jdiはの使用に関する正しい情報を持っていますGOPATH。バイナリも作成する場合は、ディレクトリにレベルを1つ追加することもできます。

~/projects/src/
    myproj/
        mypack/
            lib.go
            lib_test.go
            ...
        myapp/
            main.go

実行go build myproj/mypackすると、mypack依存関係とともにパッケージがビルドされます。実行go build myproj/myappすると、myappおそらくmypackライブラリを含む依存関係とともにバイナリがビルドされます。


もちろん、もし彼が実際にメインのコマンドを持っていたなら、これは理にかなっています。ライブラリパッケージを作成しているようです。
jdi 2012

49

私はいくつかのGoプロジェクトを研究してきましたが、かなりのバリエーションがあります。前者はmainパッケージのプロジェクトルートディレクトリのすべてのほぼすべてをダンプし、後者はすべてをsrcディレクトリに置く傾向があるため、CからだれがJavaから来ているかを知ることができます。ただし、どちらも最適ではありません。インポートパスと他のユーザーによるインポートパスの再利用に影響を与えるため、それぞれに影響があります。

最良の結果を得るために、私は次のアプローチを考え出しました。

myproj/
  main/
    mypack.go
  mypack.go

どこにmypack.goありpackage mypackmain/mypack.go(明らかに)package mainです。

追加のサポートファイルが必要な場合は、2つの選択肢があります。それらすべてをルートディレクトリに保存するか、プライベートサポートファイルをlibサブディレクトリに配置します。例えば

myproj/
  main/
    mypack.go
  myextras/
    someextra.go
  mypack.go
  mysupport.go

または

myproj.org/
  lib/
    mysupport.go
    myextras/
      someextra.go
  main/
    mypack.go
  mypage.go

lib別のプロジェクトでインポートすることを意図していない場合にのみ、ファイルをディレクトリに配置してください。つまり、プライベートサポートファイルの場合です。これが、libパブリックインターフェイスとプライベートインターフェイスを分離することの背後にある考え方です。

このようにするとmyproj.org/mypack、他のプロジェクトでコードを再利用するための優れたインポートパスが得られます。使用する場合lib、内部サポートファイルには、それを示すインポートパスがありmyproj.org/lib/mysupportます。

プロジェクトをビルドするときはmain/mypack、たとえばを使用しますgo build main/mypack。複数の実行可能ファイルがある場合は、main個別のプロジェクトを作成せずに、それらを分離できます。例main/myfoo/myfoo.gomain/mybar/mybar.go


14
Idomaticはcmd/nameOfMyExecutable、メインパッケージのサブディレクトリを使用するcmd/…ことです(複数のコマンドがある場合にのみ必要です。を参照してくださいgolang.org/x/tools/cmd。それ以外の場合は、それを入れ替えてmain.goトップレベルに置くのが一般的です)。あなたがそれを持っている方法はgo install、「メイン」(または「main.exe」)実行可能ファイルを作成します。また、慣用的には、internal他の場所で使用することを意図していない、パッケージ/プログラムの内部のサブパッケージにサブディレクトリを使用します(Goの将来のバージョンでは、internalこの方法で行われるパッケージのインポートを他の誰も強制しないと予想されます)。
Dave C


13

Goプロジェクトを整理する標準的な方法はないようですが、https://golang.org/doc/code.htmlは、ほとんどのプロジェクトのベストプラクティスを指定しています。jdiの答えは良いですが、githubまたはbitbucketを使用していて、追加のライブラリもある場合は、次の構造を作成する必要があります。

~/projects/
bin/
pkg/
src/
  github.com/
    username/
        mypack/
            foo.go
            bar.go
            mypack_test.go
        mylib/
            utillib.go
            utillib_test.go

このようにすることで、他のプロジェクトで使用でき、「go get」で取得できるmylibの個別のリポジトリを作成できます。mypackプロジェクトは、「github.com/username/mylib」を使用してライブラリをインポートできます。詳細については:

http://www.alexvictorchan.com/2014/11/06/go-project-structure/


6

ファイルを同じディレクトリに保存し、package mainすべてのファイルで使用します。

myproj/
   your-program/
      main.go
      lib.go

次に実行します:

~/myproj/your-program$ go build && ./your-program

これはどのように機能しますか?main.goはパッケージmainである必要があります。おそらくlib.goが別のパッケージにある場合、goツールは1つのフォルダーに2つのパッケージを含めることはできないと不平を言います。
I82多くの2014年

1
@ I82Much OPは、メインプログラムである1つのパッケージを多くのファイルに分割する方法を要求します。この場合、lib.goは同じパッケージにあります。
グスタフ

ああ、説明してくれてありがとう。
I82Much

@Gustav、同じ質問があります。lib.goにパッケージmainを置くと、lib.goで定義された関数を呼び出せないようです。
Qian Chen

@ElgsQianChenメソッドは公開する必要があります。大文字で始める必要があります。たとえば、MyMethod()またはMyStruct {...}。
グスタフ

6

go get repository_remote_urlコマンドがの下のプロジェクト構造をどのように管理するかを見てみましょう$GOPATH。実行するgo get github.com/gohugoio/hugoと、リポジトリが複製されます。

$ GOPATH / src / repository_remote / user_name / project_name


$ GOPATH / src / github.com/gohugoio/hugo

これは、最初のプロジェクトパスを作成するための良い方法です。次に、プロジェクトのタイプとは何か、その内部構造がどのように編成されているかを見てみましょう。コミュニティ内のすべてのgolangプロジェクトは、以下に分類できます

  • Libraries (実行可能なバイナリなし)
  • Single Project (実行可能なバイナリが1つだけ含まれています)
  • Tooling Projects (複数の実行可能バイナリが含まれています)

通常、golangプロジェクトファイルは、DDDPODなどの設計原則に基づいてパッケージ化できます。

利用可能なgoプロジェクトのほとんどは、このパッケージ指向の設計に従います

パッケージ指向の設計により、開発者は自身のパッケージ内にのみ実装を保持することが推奨されます。ただし、/internalこれらのパッケージが互いに通信できないパッケージは除きます。


図書館

  • データベースドライバーqtなどのプロジェクトは、このカテゴリに分類できます。
  • 以下のようないくつかのライブラリのカラーは今や他のパッケージなしでフラットな構造に従います。
  • これらのライブラリプロジェクトのほとんどは、internalというパッケージを管理しています。
  • /internal パッケージは主に、他のプロジェクトから実装を隠すために使用されます。
  • 実行可能なバイナリがないため、メインの funcを含むファイルはありません。

 ~/$GOPATH/
    bin/
    pkg/
    src/
      repository_remote/
        user_name/
            project_name/
              internal/
              other_pkg/

単一プロジェクト

  • hugoetcdなどのプロジェクトには、ルートレベルで単一のメイン関数があり
  • ターゲットは単一のバイナリを生成することです

ツーリングプロジェクト

  • kubernetesgo-ethereumなどのプロジェクトには、cmdと呼ばれるパッケージにまとめられた複数の主要な機能があります
  • cmd/ パッケージは、ビルドするバイナリ(ツール)の数を管理します

 ~/$GOPATH/
    bin/
    pkg/
    src/
      repository_remote/
        user_name/
            project_name/
              cmd/
                binary_one/
                   main.go
                binary_two/
                   main.go
                binary_three/
                   main.go
              other_pkg/
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.