Go Wiki: GOPATH
GOPATH変数
標準ライブラリ以外の依存関係を使用するGo開発は、Goモジュールを使用して行われます。Goモジュールを使用する場合、GOPATH変数(Unixでは$HOME/go、Windowsでは%USERPROFILE%\goがデフォルト)は以下の目的で使用されます。
go installコマンドは、バイナリを$GOBINにインストールします。これはデフォルトで$GOPATH/binです。go getコマンドは、ダウンロードしたモジュールを$GOMODCACHEにキャッシュします。これはデフォルトで$GOPATH/pkg/modです。go getコマンドは、ダウンロードしたチェックサムデータベースの状態を$GOPATH/pkg/sumdbにキャッシュします。
GOPATH変数の詳細については、goコマンドのドキュメントを参照してください。このページの残りの部分は、現在非推奨となっているGOPATH開発モードに関するものです。
GOPATH開発モード
Goモジュールが登場する前は、依存関係を使用するGo開発は「GOPATH開発モード」、略して「GOPATHモード」を使用していました。GOPATHモードでは、goコマンドはGOPATH変数を以下の目的で使用していました。
go installコマンドは、バイナリを$GOBINにインストールしていました。これはデフォルトで$GOPATH/binです。go installコマンドは、import "example.com/y/z"のコンパイル済みパッケージファイルを$GOPATH/pkg/example.com/y/z.aにインストールしていました。go getコマンドは、import "example.com/y/z"を満たすソースコードを$GOPATH/src/example.com/y/zにダウンロードしていました。
GOPATH開発モードの非推奨化と削除
Goモジュールは、Goエコシステム全体にパッケージバージョンの概念を追加するためのGOPATH開発モードの代替です。
GOPATH開発モードからGoモジュールへの移行は、多くのGoリリースにわたって徐々に行われてきました。
-
Go 1.11 (2018年8月) では、
GO111MODULE変数が導入され、デフォルトはautoでした。GO111MODULE=offの場合、goコマンドは常にGOPATHモードを使用しました。GO111MODULE=onの場合、goコマンドは常にモジュールモードを使用しました。GO111MODULE=auto(またはGO111MODULEが設定されていない場合)の場合、goコマンドは現在のディレクトリに基づいてモードを決定しました。現在のディレクトリが$GOPATH/srcの**外**にあり、ルートにgo.modファイルがあるソースツリー内にある場合、goコマンドはGoモジュールモードを使用しました。それ以外の場合、goコマンドはGOPATHモードを使用しました。このルールは、$GOPATH/srcで実行されるすべてのコマンドがautoモードで影響を受けないようにしつつ、ユーザーが他のディレクトリでモジュールを試せるようにしました。 -
Go 1.13 (2019年8月) では、
GO111MODULE=autoモードが調整され、$GOPATH/srcの制限がなくなりました。$GOPATH/src内のディレクトリにgo.modファイルがある場合、そのディレクトリ内またはその下のディレクトリで実行されるコマンドはモジュールモードを使用するようになりました。これにより、ユーザーはチェックアウトしたコードをインポートベースの階層で整理し続けることができ、個々のチェックアウトにモジュールを使用できます。 -
Go 1.16 (2021年2月) では、デフォルトが
GO111MODULE=onに変更され、常にモジュールモードを使用するようになります。つまり、GOPATHモードはデフォルトで完全に無効になります。もう1つのリリースでGOPATHモードを使用する必要があるユーザーは、明示的にGO111MODULE=autoまたはGO111MODULE=offを設定できます。 -
Go 1.NN (???) では、
GO111MODULE設定とGOPATHモードが完全に削除され、常にモジュールモードを使用するようになります。
GOPATH開発モードの削除は、GOPATH変数の削除を**意味しません**。GOPATH変数は、このページの上部に記載されている目的のために引き続き使用されます。
FAQ
GOPATH変数は削除されますか?
いいえ。GOPATH変数(環境変数またはgo env -wで設定)は**削除されません**。このページの上部に記載されているように、デフォルトのバイナリインストール場所、モジュールキャッシュ場所、およびチェックサムデータベースキャッシュ場所を決定するために引き続き使用されます。
GOPATH/src/import/pathにコードを書き続けることはできますか?
はい。多くのGo開発者は、この慣習が提供する構造を評価し、その中にモジュールリポジトリをチェックアウトしています。モジュールを使い始めるために必要なコードは、go.modファイルだけです。go mod initを参照してください。
あるリポジトリをGOPATH/srcで、別のリポジトリで行われた変更に対してコンパイルするにはどうすればよいですか?
あるモジュールをビルドする際に、別のモジュールで未公開の変更を使用したい場合は、そのモジュールのgo.modにreplace行を追加できます。
例えば、golang.org/x/websiteとgolang.org/x/toolsを$GOPATH/src/golang.org/x/websiteと$GOPATH/src/golang.org/x/toolsにチェックアウトしている場合、websiteのローカルビルドでtoolsの変更を自動的に使用するには、$GOPATH/src/golang.org/x/website/go.modにこれを追加します。
replace golang.org/x/tools => ../tools
もちろん、replaceディレクティブは$GOPATHについて何も知りません。この2つを$HOME/mycode/websiteと$HOME/mycode/toolsにチェックアウトした場合でも、同じ行が機能します。
なぜGOPATH開発モードは削除されるのですか?
GOPATH開発モードの核心は、本質的にそのようなすべてのreplace行を自動的に提供することです。これにより、依存関係のためにビルドするコードが、たまたまコンピュータにチェックアウトされているコードになります。これは、ビルドが、たまたま放置されている古いチェックアウト(忘れているかもしれない)によって影響を受けることを意味します。同じトップレベルのリポジトリの同じバージョンから開始しても、あるマシンで得られるビルドが別のマシンと異なる可能性があります。そして、同じプロジェクトの別の開発者が得るビルドと、あなたが得るビルドが異なる可能性があります。Goモジュールは、これらすべての再現性の懸念に対処します。これらすべての問題の根本原因は、GOPATHモードにパッケージ**バージョン**の概念がないことです。
再現性に加えて、Goモジュールはプロキシと安全なダウンロードを処理する明確な方法を提供します。プロジェクトをgit cloneしてその依存関係を取得すると、それらの依存関係は暗号的にチェックされ(go.sumファイルを使用して)、元の開発者が使用したものと同じビットであることを確認します。信頼できる部分はトップレベルのgit cloneだけです。ここでも、これはGOPATHモードとは対照的に、Goモジュールがパッケージバージョンの概念を持っているからこそ可能です。
そして、Go自体の将来の進化のために、モジュールは特定のファイルツリーがどのバージョンのGo言語で書かれているかを明確に示します。これにより、問題のある機能(例えば、多くの人が"1"を生成すると思っているが、実際には"\x01"(Ctrl-A)を生成するstring(1))をGoの後のバージョンで無効にし、古いプログラムをビルドし続けることができます(古いバージョンのGo用に書かれたものであると明示的にマークされているため)。
これら以外にも多くの例があります。
GOPATH開発モードでは、今日の形ではこれらはどれも不可能です。GOPATHモードを廃止せずに、Goエコシステムを進化させ、Goモジュールのこれらの重要な特性に本当に依存し始めることはできません。
(また、GOPATHモードにそれらを追加するだけではだめなのかと尋ねるかもしれません。答えは、そうしました。そしてその結果がGoモジュールです。)
GOPATH開発モードの非推奨化はいつ決定されましたか?
当初の計画ではGo 1.13でGOPATHモードを非推奨にする予定でしたが、できるだけ多くのGoユーザーのためにモジュールをさらに堅牢にするために余分な時間をかけたかったため、非推奨化はそのリリースから延期されました。issue #41330とgolang-toolsグループでの議論では、GOPATHの非推奨化に関する残りのブロッカーは特定されなかったため、上記のタイムラインに記載されているように、Go 1.16でスケジュールされ、将来のリリースで削除されることになりました。
GOPATH開発モードからGoモジュールへの移行に関して、他に質問がある場合はどうすればよいですか?
リソースのリストについては、golang.org/helpを参照してください。これらの中に適切なものがない場合は、遠慮なくここで問題を報告してください。私たちは、誰もがGoモジュールをうまく採用できることを望んでいます。
このコンテンツはGo Wikiの一部です。