web-dev-qa-db-ja.com

gopathなしでローカルパッケージをインポートする方法は?

私はGOPATHを使ったことがありますが、今号では助けにはなりません。プロジェクトに固有のパッケージを作成できるようにしたいです。

myproject/
├── binary1.go
├── binary2.go
├── package1.go
└── package2.go

私は複数の方法を試しましたが、どうやってpackage1.gobinary1.gobinary2.goなどで動作させることができますか?

例えば; import "package1"を実行してからgo build binary1.goを実行できるようにしたいのですが、パッケージがGOROOTまたはGOPATHに見つからないというエラーが発生することなく、すべて正常に動作します。このような機能が必要なのは、大規模プロジェクトのためです。他の複数のパッケージを参照したり、それらを1つの大きなファイルに保存したりする必要はありません。

125
user1529891

依存関係管理の概要に移動します。

  • Goバージョンがx >= go 1.11の場合はvgo
  • Goバージョンがgo 1.6 >= x < go 1.11の場合はdepまたはvendor
  • Goバージョンがx < go 1.6の場合は手動で

編集3:囲碁1.11は 置換vgoになる機能depを持っています。

vgoを使用するには、 Modules のドキュメントを参照してください。以下のTLDR:

export GO111MODULE=on
go mod init
go mod vendor # if you have vendor/ folder, will automatically integrate
go build

このメソッドは、プロジェクトディレクトリにgo.modというファイルを作成します。その後、go buildを使用してプロジェクトをビルドできます。 GO111MODULE=autoが設定されている場合、プロジェクトは$GOPATHに入れることはできません。


編集2:販売方法はまだ有効で問題なく動作します。このvendordepが作成されたため、vgoは主に手動のプロセスです。


編集1:私の昔のやり方はうまくいきますが、それはもはや「正しい」やり方ではありません。 Go 1.6ではデフォルトで有効になっているvendor機能、vgo、またはdepを使うべきです。 参照 。あなたは基本的にあなたの "外部"または "依存"パッケージをvendorディレクトリ内に追加します。コンパイル時に、コンパイラはこれらのパッケージを最初に使用します。


見つかりました。 package1のサブフォルダを作成し、import "./package1"binary1.goスクリプトでbinary2.goを使ってインポートすることで、GOPATHを使ってローカルパッケージをインポートできました。

binary1.go

...
import (
        "./package1"
      )
...

だから私の現在のディレクトリ構造はこのようになります:

myproject/
├── binary1.go
├── binary2.go
├── package1/
│   └── package1.go
└── package2.go

また、相対パス(少なくとも1.5以降)も機能することに注意してください。例えば:

import "../packageX"
145
user1529891

「ローカルパッケージ」のようなものはありません。ディスク上のパッケージの編成は、パッケージの親子関係とは直交しています。パッケージによって形成される唯一の実際の階層は依存関係ツリーです。これは一般的にディレクトリツリーを反映していません。

ただ使う

import "myproject/packageN"

正当な理由がないためにビルドシステムと戦わないでください。たとえば、相対的なインポートパスを持つプロジェクトはうまくいかないため、1インポートあたり1ダースの文字数を節約するのは、良い理由ではありません。

インポートパスの概念には、いくつかの重要な特性があります。

  • インポートパスはグローバルに一意にすることができます。
  • GOPATHとともに、インポートパスをディレクトリパスに明確に変換できます。
  • GOPATHの下のディレクトリパスはすべて、インポートパスに明確に変換できます。

上記のすべては、相対インポートパスを使用することによって台無しにされます。それをしません。

シモンズ:相対的なインポートを使うGoのコンパイラテストでは、レガシーコードの中にいくつかの場所があります。 ATM、これが相対インポートがまったくサポートされている唯一の理由です。

62
zzzz

おそらくあなたはあなたのパッケージをモジュール化しようとしています。 package1package2は、ある意味で同じパッケージの一部ですが、読みやすくするためにこれらを複数のファイルに分割していると思います。

前のケースがあなたのものだったら、あなたはそれらの倍数ファイルに同じパッケージ名を使うことができ、同じファイルがあるかのようになります。

これは一例です。

add.go

package math

func add(n1, n2 int) int {
   return n1 + n2
}

subtract.go

package math

func subtract(n1, n2 int) int {
    return n1 - n2
}

donothing.go

package math

func donothing(n1, n2 int) int {
    s := add(n1, n2)
    s = subtract(n1, n2)
    return s
}

私はGoのエキスパートではありません。これがStackOveflowの私の最初の投稿ですので、何かアドバイスがあれば好評です。

40

私は同様の問題を抱えており、私が現在使っている解決策はGo 1.11モジュールを使っています。次のような構造になっています

- projects
  - go.mod
  - go.sum
  - project1
    - main.go
  - project2
    - main.go
  - package1
    - lib.go
  - package2
    - lib.go

そして、私はを使用してproject1とproject2からpackage1とpackage2をインポートすることができます

import (
    "projects/package1"
    "projects/package2"
)

go mod init projectsを実行した後。 project1およびproject2ディレクトリからgo buildを使用することも、projectsディレクトリからgo build -o project1/exe project1/*.goを実行することもできます。

この方法の欠点は、すべてのプロジェクトがgo.modで同じ依存関係リストを共有することになることです。私はまだこの問題の解決策を探していますが、それはそれが根本的かもしれないように見えます。

11
Mad Wombat

プロジェクトに "local"パッケージを追加するには、フォルダ( "package_name"など)を追加します。そして、そのフォルダにあなたの実装ファイルを置いてください。

src/github.com/GithubUser/myproject/
 ├── main.go
 └───package_name
       └── whatever_name1.go
       └── whatever_name2.go

あなたのpackage mainでこれを行います:

import "github.com/GithubUser/myproject/package_name"

package_nameはフォルダー名で、ファイルwhatever_name1.goおよびwhatever_name2.goで使用されているパッケージ名と一致していなければなりません。言い換えれば、サブディレクトリを持つすべてのファイルは同じパッケージであるべきです。

インポートで親フォルダーへのパス全体を指定する限り、さらにサブディレクトリーをネストすることができます。

4
Homan