web-dev-qa-db-ja.com

リポジトリで複数のモジュールを使用すると、Go getでローカルパッケージが見つかりません

ローカルモジュールを定義してメインプログラムにインポートしたいので、goの新しいモジュールシステムに問題があります。ローカルパッケージは、メインパッケージ/ルートフォルダーのフォルダーにあります。 $GOPATHの外部にある次のプロジェクト構造を想像してください。

プロジェクト構造

./main.go

package main

import "fmt"
import "example.com/localModule/model"

func main() {
    var p = model.Person{name: "Dieter", age:25}
    fmt.Printf("Hello %s\n", p.name)
}

./model/person.go

package model

type Person struct {
    name string
    age int
}

ルートフォルダーで、呼び出してモジュールを初期化しました

go mod init example.com/localModule

model/フォルダーで、呼び出してサブモジュールを初期化しました

go mod init example.com/localModule/model

エラー

次のコマンドを呼び出すルートフォルダーで失敗します。

$ go get
go build example.com/localModule/model: no Go files in

$ go build
main.go:4:8: unknown import path "example.com/localModule/model": cannot find module providing package example.com/localModule/model

Go getのエラーメッセージが途切れます。間違って解析することはありません。

モジュールをサーバーにプッシュする予定はなく、ローカルパッケージmodelを参照する方法が必要だったため、それぞれexample.com/localModule/example.com/localModule/modelを選択しました。

MacOS 10.13.6を実行しているMacbookでgo1.11 darwin/AMD64を使用しています。

22
Tobs.Core

Requireステートメントとそれに対応するreplaceステートメントをgo.modの相対ファイルパスに追加することで、要求するようなローカルの「サブ」モジュールを作成できます。

「ルート」内./go.mod:

module example.com/localModule

require example.com/localModule/model v0.0.0

replace example.com/localModule/model v0.0.0 => ./model
32
Jostein Stuhaug

根本的な問題

このエラーが発生する理由は、ローカルディスクでお互いを見つける方法がわからない2つのモジュールを定義したためです。

$ go build
main.go:4:8: unknown import path "example.com/localModule/model": 
 cannot find module providing package example.com/localModule/model

解決策1:replace

次のようなreplaceディレクティブをトップモジュールのgo.modファイルに追加できます。

replace example.com/localModule/model v0.0.0 => ./model

これにより、最上位モジュールがディスク上の他のモジュールを見つけることができます。これは、モジュールwikiの replace FAQ および "Multi-module repositories" セクションで詳細に説明されています。

ただし、これはより複雑な解決策であり、適切にするのが難しく、通常は継続的な作業であり、現在のモジュールを除くすべてのモジュールでreplaceが無視されるなどの制限があります。ほとんどの人にとって、マルチモジュールリポジトリはおそらく彼らが望むものではありません。この時点で、単一のリポジトリに複数のモジュールを実際に必要とすることは比較的まれです。

解決策2:1つのレポ== 1つのモジュール

replaceディレクティブを使用することは可能ですが、より一般的で簡単な解決策は次のとおりです。

  • リポジトリに単一のgo.modファイルがあり、
  • その単一のgo.modファイルをリポジトリのルートに配置します。

これは非常にシンプルなソリューションであり、リポジトリ内の2つのパッケージがreplaceを必要とせずに自動的にお互いを見つけることができ、報告したエラーメッセージを回避できることを意味します。

replaceはマルチモジュールリポジトリで、vsシングルモジュールリポジトリですか?

Russ Coxが #26664 でコメントしました:

パワーユーザーを除くすべてのユーザーにとって、1つのレポ= 1つのモジュールという通常の規則を採用することになるでしょう。リポジトリcanに複数のモジュールを含めることは、コードストレージオプションの長期的な進化にとって重要ですが、ほとんどの場合、デフォルトでやりたいことではありません。

代わりに、単一のリポジトリ内で複数のモジュールを定義したい場合、適切に行う方法についてかなりの微妙な違いがあり、モジュールwikiの セクション全体 について読む必要がありますこのアドバイスを含む、単一のリポジトリ内の複数のモジュールに関連する複雑さを管理する方法:

モジュールの追加、モジュールの削除、および単一リポジトリ内の複数モジュールによるモジュールのバージョン管理かなりの注意と熟考が必要なので、単一モジュールリポジトリの管理はほとんどの場合より簡単でシンプルです既存のリポジトリ。

2
typical182