main.go
の外でGoモジュール(goバージョン> = 1.11)を使用する場合、$GOPATH
からローカルパッケージにコードを分解する方法が見つかりません。
go.mod
に含める必要がある外部依存関係をインポートしていません。このGoモジュールのソースコードをローカルに整理しようとしています。
ファイルmain.go
:
package main
// this import does not work
import "./stuff"
func main() {
stuff.PrintBaz()
}
ファイル./stuff/bar.go
(ローカルパッケージを装ったもの):
package stuff
import "log"
type Bar struct {
Baz int
}
func PrintBaz() {
baz := Bar{42}
log.Printf("Bar struct: %v", baz)
}
ファイルgo.mod
(コマンドgo mod init foo
):
module foo
go 1.12
go run main.go
を実行する場合:
import "./stuff"
の場合、build command-line-arguments: cannot find module for path _/home/<PATH_TO>/fooprj/stuff
が表示されます。import "stuff"
の場合、build command-line-arguments: cannot load stuff: cannot find module providing package stuff
が表示されます。import stuff "./stuff"
を使用すると、build command-line-arguments: cannot find module for path _/home/<PATH_TO>/fooprj/stuff
が再び表示されます。ローカルモジュールをgoモジュールで動作させる方法が見つかりません。
go.mod
)内の他のGoコードにローカルパッケージをインポートするにはどうすればよいですか?最初に、プロジェクトの名前を選択し、それをgo.modファイルに書き込む必要があります。この名前は、プロジェクトのルートディレクトリに属しています。作成する新しいパッケージはそれぞれ独自のサブディレクトリ内に配置する必要があり、その名前はディレクトリ名と一致する必要があります。
go.mod:
module myprojectname
または(推奨される方法、詳細については、@ typical182の 下の回答 を参照してください)
module github.com/myname/myproject
次に、プロジェクトのパッケージを次のようにインポートします。
import myprojectname/stuff
または
import github.com/myname/myproject/stuff
パッケージstuff
のファイルは、プロジェクトのstuff
ディレクトリ内に配置する必要があります。これらのファイルには好きな名前を付けます。
また、より深いプロジェクト構造を作成することも可能です。たとえば、ソースコードファイルを他のファイル(アプリ構成、Dockerファイル、静的ファイルなど)から分離することにしました。 stuff
ディレクトリをpkg
内に移動しましょう。pkg/stuff
内のすべてのgoファイルには、まだstuff
パッケージ名が付いています。スタッフパッケージをインポートするには、次のように記述します。
import myprojectname/pkg/stuff
github.com/myuser/myproject/pkg/db/provider/postgresql
のように、階層内にさらにレベルを作成することを妨げるものはありません。ここで、
github.com/myuser/myproject
-プロジェクト名。postgresql
-パッケージ名。pkg/db/provider/postgresql
-プロジェクトのルートに対するパッケージの相対パス。Goモジュールの詳細については、こちらをご覧ください。 https://github.com/golang/go/wiki/Modules
このリポジトリをチェックして、プロジェクトの編成で使用されるさまざまなパターンに関する有用な情報を取得してください。 https://github.com/golang-standards/project-layoutpkg
ディレクトリ内に移動すると構造内でpkg
ディレクトリを使用しているオープンソースプロジェクトを見つけます。
最も一般的で簡単なアプローチは次のとおりです。
go.mod
_を使用し、go.mod
_ファイルをリポジトリルートに配置し、go.mod
_ のmodule
行で宣言されたモジュールパスとしてリポジトリ名を使用しますme.io/mymod
_などのVCSホストベースのインポートパスを使用する場合は、リポジトリ名の代わりにカスタムインポートパスを使用します_go.mod
_)で.たとえば、リポが_github.com/my/repo
_の場合、単一の_go.mod
_をリポルートに配置し、最初の行を_module github.com/my/repo
_とします。これは、リポジトリルートにcd
'して_go mod init github.com/my/repo
_を実行することで作成できます。
これに従うことで、モジュールを使用してハッピーパスを維持でき、複数の微妙な問題を回避できます。
Russ Coxが #26664 にコメントしました:
パワーユーザーを除くすべてのユーザーは、1つのリポジトリ= 1つのモジュールという通常の規則を採用する必要があります。リポジトリcanに複数のモジュールが含まれていることは、コードストレージオプションの長期的な進化にとって重要ですが、ほとんどの場合、デフォルトで実行する必要はありません。
"Multi-module Repositories" FAQモジュールwikiのセクション)に、マルチモジュールリポジトリに関する詳細があります。このセクションは、上記の推奨事項を回避することを検討している人は、その全体を読む必要があります。
_go.mod
_を設定すると、パッケージをディレクトリに配置できますが、_go.mod
_を含むディレクトリの下のディレクトリと、_go.mod
_を含むディレクトリに収まるように見えます。コードをパッケージに配置する方法に関する3つの優れた記事:
これらの記事はモジュールの導入以前の古典ですが、それらの哲学は、モジュール内でパッケージを配置する方法にも適用されます。
モジュールを含む別のパッケージをインポートするときは、常にモジュールパスを含むフルパスを使用します。これは、同じモジュールに別のパッケージをインポートする場合にも当てはまります。たとえば、モジュールが_go.mod
_でモジュールのアイデンティティをモジュール_github.com/my/repo
_として宣言し、次のような組織の場合:
_repo/
├── go.mod <<<<< Note go.mod is located in repo root
├── pkg1
│ └── pkg1.go
└── pkg2
└── pkg1.go
_
次に、_pkg1
_は、ピアパッケージを_import "github.com/my/repo/pkg2"
_としてインポートします。 _import "../pkg2"
_や_import "./subpkg"
_のような相対インポートパスは使用できないできないことに注意してください。 (これは、OPが上記の_import "./stuff"
_でヒットしたものの一部です)。
Goモジュールは、1つのユニットとして一緒にバージョン管理される、関連するGoパッケージのコレクションです。モジュールは正確な依存関係の要件を記録し、再現可能なビルドを作成します。
リポジトリ、モジュール、パッケージ間の関係の要約:
package foo
_ステートメントで独自のパッケージを宣言します。import "github.com/my/repo/pkg1"
_などのインポートステートメントで指定されたimport pathを介して別のパッケージからコードをインポートします。インポートパスは、そのパッケージが同じモジュールにあるか別のモジュールにあるかに関係なく、常にそのパッケージのモジュールパスで始まります。