依存関係の管理
コードが外部パッケージを使用する場合、これらのパッケージ(モジュールとして配布されます)は依存関係となります。時間の経過とともに、それらをアップグレードしたり、置き換えたりする必要があるかもしれません。Goは、外部依存関係を組み込む際にGoアプリケーションを安全に保つのに役立つ依存関係管理ツールを提供します。
このトピックでは、コードに取り込んだ依存関係を管理するためのタスクを実行する方法について説明します。これらのほとんどはGoツールで実行できます。このトピックでは、役立つ可能性のあるその他の依存関係関連タスクをいくつか実行する方法についても説明します。
こちらも参照
- モジュールとしての依存関係の操作に慣れていない場合は、簡単な紹介として入門チュートリアルをご覧ください。
goコマンドを使用して依存関係を管理すると、要件の一貫性が保たれ、go.modファイルの内容が有効であることが保証されます。コマンドの参照については、コマンドgoを参照してください。go helpcommand-nameと入力することで、コマンドラインからヘルプを取得することもできます(例:go help mod tidy)。- 依存関係の変更を行うために使用するGoコマンドは、go.modファイルを編集します。ファイルの内容の詳細については、go.modファイルリファレンスを参照してください。
- エディタまたはIDEにGoモジュールを認識させることで、それらの管理作業が簡単になります。Goをサポートするエディタの詳細については、エディタプラグインとIDEを参照してください。
- このトピックでは、他の人が使用するモジュールを開発、公開、バージョン管理する方法については説明していません。詳細については、モジュールの開発と公開を参照してください。
依存関係の使用と管理のワークフロー
Goツールを使用して便利なパッケージを取得し、使用できます。pkg.go.devで、役立つ可能性のあるパッケージを検索し、goコマンドを使用してそれらのパッケージを独自のコードにインポートして関数を呼び出すことができます。
以下に、最も一般的な依存関係管理の手順をリストします。それぞれの詳細については、このトピックのセクションを参照してください。
- pkg.go.devで便利なパッケージを見つける。
- コードで必要なパッケージをインポートする。
- 依存関係追跡のためにコードをモジュールに追加する(まだモジュールに含まれていない場合)。依存関係追跡の有効化を参照してください。
- 管理できるように外部パッケージを依存関係として追加する。
- 時間の経過とともに必要に応じて依存関係のバージョンをアップグレードまたはダウングレードする。
モジュールとしての依存関係の管理
Goでは、インポートするパッケージを含むモジュールとして依存関係を管理します。このプロセスは以下によってサポートされています。
- モジュールの公開とコードの取得のための分散システム。開発者は、独自のリポジトリから他の開発者が使用できるモジュールを提供し、バージョン番号を付けて公開します。
- モジュールを見つけることができるパッケージ検索エンジンとドキュメントブラウザ(pkg.go.dev)。便利なパッケージの検索とインポートを参照してください。
- モジュールの安定性と後方互換性の保証を理解するのに役立つモジュールのバージョン番号規則。モジュールのバージョン番号を参照してください。
- モジュールのソースの取得、アップグレードなど、依存関係の管理を容易にするGoツール。詳細については、このトピックのセクションを参照してください。
便利なパッケージの検索とインポート
pkg.go.devを検索して、役立つ可能性のある関数を含むパッケージを見つけることができます。
コードで使用したいパッケージを見つけたら、ページ上部にあるパッケージパスを見つけて「パスをコピー」ボタンをクリックし、パスをクリップボードにコピーします。独自のコードで、次の例のようにパスをimport文に貼り付けます。
import "rsc.io/quote"
コードがパッケージをインポートしたら、依存関係の追跡を有効にし、コンパイルのためにパッケージのコードを取得します。詳細については、コードでの依存関係追跡の有効化と依存関係の追加を参照してください。
コードでの依存関係追跡の有効化
追加する依存関係を追跡および管理するには、まずコードを独自のモジュールに入れます。これにより、ソースツリーのルートにgo.modファイルが作成されます。追加する依存関係は、そのファイルにリストされます。
コードを独自のモジュールに追加するには、go mod initコマンドを使用します。たとえば、コマンドラインからコードのルートディレクトリに移動し、次の例のようにコマンドを実行します。
$ go mod init example/mymodule
go mod initコマンドの引数は、モジュールのモジュールパスです。可能であれば、モジュールパスはソースコードのリポジトリの場所であるべきです。
最初にモジュールの最終的なリポジトリの場所がわからない場合は、安全な代替手段を使用してください。これは、所有するドメインの名前や、制御する別の名前(会社名など)と、モジュールの名前またはソースディレクトリに続くパスの組み合わせである場合があります。詳細については、モジュールの命名を参照してください。
Goツールを使用して依存関係を管理すると、ツールはgo.modファイルを更新し、依存関係の現在のリストを維持します。
依存関係を追加すると、Goツールは依存するモジュールのチェックサムを含むgo.sumファイルも作成します。Goはこれを使用して、ダウンロードしたモジュールファイルの整合性を検証します。特に、プロジェクトで作業する他の開発者にとっては重要です。
go.modファイルとgo.sumファイルをコードとともにリポジトリに含めます。
詳細については、go.modリファレンスを参照してください。
モジュールの命名
依存関係を追跡するためのモジュールを作成するためにgo mod initを実行すると、モジュールの名前として機能するモジュールパスを指定します。モジュールパスは、モジュール内のパッケージのインポートパスプレフィックスになります。他のモジュールのモジュールパスと競合しないモジュールパスを必ず指定してください。
最低限、モジュールパスは、会社名、作者名、所有者名など、その起源に関する何かを示すだけで済みます。しかし、パスはモジュールが何であるか、または何をするかについて、より記述的であることもあります。
モジュールパスは通常、次の形式です。
<prefix>/<descriptive-text>
-
プレフィックスは通常、モジュールを部分的に記述する文字列であり、その起源を記述する文字列などです。これは次のようになります。
-
Goツールがモジュールのソースコードを見つけることができるリポジトリの場所(モジュールを公開する場合に必須)。
たとえば、
github.com/<project-name>/のようになります。他の人が使用するためにモジュールを公開する可能性があると考える場合は、このベストプラクティスを使用してください。公開の詳細については、モジュールの開発と公開を参照してください。
-
制御する名前。
リポジトリ名を使用しない場合は、他の人が使用しないと確信できるプレフィックスを選択してください。良い選択は会社名です。
widgets、utilities、appなどの一般的な用語は避けてください。
-
-
記述テキストについては、プロジェクト名が良い選択です。パッケージ名が機能の記述のほとんどを担っていることを覚えておいてください。モジュールパスは、これらのパッケージ名の名前空間を作成します。
予約済みモジュールパスプレフィックス
Goは、次の文字列がパッケージ名で使用されないことを保証します。
-
test– 他のモジュールの関数をローカルでテストするように設計されたモジュールのモジュールパスプレフィックスとしてtestを使用できます。テストの一部として作成されたモジュールには、
testパスプレフィックスを使用してください。たとえば、テスト自体がgo mod init testを実行し、Goソースコード分析ツールでテストするためにそのモジュールを特定の方法で設定する場合があります。 -
example– 依存関係を追跡するためだけにモジュールを作成するチュートリアルなど、一部のGoドキュメントでモジュールパスプレフィックスとして使用されます。Goドキュメントでは、例が公開されたモジュールである可能性があることを示すために
example.comも使用することに注意してください。
依存関係の追加
公開されたモジュールからパッケージをインポートしたら、go getコマンドを使用して、そのモジュールを依存関係として管理対象に追加できます。
このコマンドは次のことを行います。
-
必要に応じて、コマンドラインで指定されたパッケージをビルドするために必要なモジュールの
requireディレクティブをgo.modファイルに追加します。requireディレクティブは、モジュールが依存するモジュールの最小バージョンを追跡します。詳細については、go.modリファレンスを参照してください。 -
必要に応じて、モジュールのソースコードをダウンロードして、それらに依存するパッケージをコンパイルできるようにします。proxy.golang.orgなどのモジュールプロキシから、またはバージョン管理リポジトリから直接モジュールをダウンロードできます。ソースはローカルにキャッシュされます。
Goツールがモジュールをダウンロードする場所を設定できます。詳細については、モジュールプロキシサーバーの指定を参照してください。
以下にいくつかの例を示します。
-
モジュール内のパッケージのすべての依存関係を追加するには、次のコマンドのようなものを実行します("."は現在のディレクトリ内のパッケージを指します)。
$ go get . -
特定の依存関係を追加するには、そのモジュールパスをコマンドの引数として指定します。
$ go get example.com/theirmodule
このコマンドは、ダウンロードする各モジュールを認証します。これにより、モジュールが公開された時点から変更されていないことが保証されます。モジュールが公開されてから変更された場合(たとえば、開発者がコミットの内容を変更した場合)、Goツールはセキュリティエラーを表示します。この認証チェックは、改ざんされた可能性のあるモジュールからあなたを保護します。
特定の依存関係バージョンの取得
go getコマンドでバージョンを指定することにより、特定のバージョンの依存関係モジュールを取得できます。このコマンドはgo.modファイルのrequireディレクティブを更新します(ただし、手動で更新することもできます)。
次のような場合にこれを行いたいかもしれません。
- 試すために、モジュールの特定のプレリリースバージョンを取得したい場合。
- 現在必要なバージョンが機能しないことが判明したため、信頼できるとわかっているバージョンを取得したい場合。
- すでに必要なモジュールをアップグレードまたはダウングレードしたい場合。
以下に、go getコマンドの使用例を示します。
-
特定の番号付きバージョンを取得するには、モジュールパスの後に
@記号と目的のバージョンを付けます。$ go get example.com/theirmodule@v1.3.4 -
最新バージョンを取得するには、モジュールパスの後に
@latestを付けます。$ go get example.com/theirmodule@latest
次のgo.modファイルのrequireディレクティブの例(詳細についてはgo.modリファレンスを参照)は、特定のバージョン番号を要求する方法を示しています。
require example.com/theirmodule v1.3.4
利用可能なアップデートの検出
現在のモジュールですでに使用している依存関係の新しいバージョンがあるかどうかを確認できます。go listコマンドを使用して、モジュールの依存関係のリストと、そのモジュールで利用可能な最新バージョンを表示します。利用可能なアップグレードを発見したら、コードでそれらを試して、新しいバージョンにアップグレードするかどうかを決定できます。
go listコマンドの詳細については、go list -mを参照してください。
以下にいくつかの例を示します。
-
現在のモジュールの依存関係であるすべてのモジュールと、それぞれで利用可能な最新バージョンをリスト表示します。
$ go list -m -u all -
特定のモジュールで利用可能な最新バージョンを表示します。
$ go list -m -u example.com/theirmodule
依存関係のアップグレードまたはダウングレード
Goツールを使用して利用可能なバージョンを検出し、別のバージョンを依存関係として追加することで、依存関係モジュールをアップグレードまたはダウングレードできます。
-
新しいバージョンを検出するには、利用可能なアップデートの検出で説明されているように
go listコマンドを使用します。 -
特定のバージョンを依存関係として追加するには、特定の依存関係バージョンの取得で説明されているように
go getコマンドを使用します。
コードの依存関係の同期
コードのインポートされたすべてのパッケージの依存関係を管理していることを確認するとともに、インポートしなくなったパッケージの依存関係を削除することもできます。
これは、コードと依存関係に変更を加えていた場合、管理された依存関係とダウンロードされたモジュールのコレクションを作成したものの、それがコードでインポートされたパッケージによって具体的に必要なコレクションと一致しなくなった場合に役立ちます。
管理された依存関係セットを整理するには、go mod tidyコマンドを使用します。このコマンドは、コードでインポートされたパッケージのセットを使用して、go.modファイルを編集し、必要だが不足しているモジュールを追加します。また、関連するパッケージを提供しない未使用のモジュールも削除します。
このコマンドには引数はなく、削除されたモジュールに関する情報を出力する-vフラグのみがあります。
$ go mod tidy
未公開モジュールコードに対する開発とテスト
コードが公開されていない可能性のある依存関係モジュールを使用するように指定できます。これらのモジュールのコードは、それぞれのリポジトリ、それらのリポジトリのフォーク、またはそれらを使用する現在のモジュールと同じドライブ上にある可能性があります。
次のような場合にこれを行いたいかもしれません。
- 外部モジュールのコードに独自の変更を加えたい場合(フォークおよび/またはクローン作成後など)。たとえば、モジュールへの修正を準備し、それをプルリクエストとしてモジュールの開発者に送信したい場合があります。
- 新しいモジュールを構築中で、まだ公開していないため、
go getコマンドでアクセスできるリポジトリで利用できない場合。
ローカルディレクトリ内のモジュールコードの要求
必要なモジュールのコードが、それを必要とするコードと同じローカルドライブにあることを指定できます。次のような場合にこれが役立つことがあります。
- 独自のモジュールを開発し、現在のモジュールからテストしたい場合。
- 外部モジュールの問題を修正したり、機能を追加したりし、現在のモジュールからテストしたい場合。(外部モジュールを独自のリポジトリのフォークから要求することもできることに注意してください。詳細については、独自のリポジトリフォークからの外部モジュールコードの要求を参照してください。)
Goコマンドにモジュールコードのローカルコピーを使用するように指示するには、go.modファイル内のreplaceディレクティブを使用して、requireディレクティブで指定されたモジュールパスを置き換えます。ディレクティブの詳細については、go.modリファレンスを参照してください。
次のgo.modファイルの例では、現在のモジュールは外部モジュールexample.com/theirmoduleを要求しており、置き換えが正しく機能することを確認するために存在しないバージョン番号(v0.0.0-unpublished)が使用されています。次に、replaceディレクティブは元のモジュールパスを、現在のモジュールのディレクトリと同じレベルにあるディレクトリである../theirmoduleに置き換えます。
module example.com/mymodule
go 1.23.0
require example.com/theirmodule v0.0.0-unpublished
replace example.com/theirmodule v0.0.0-unpublished => ../theirmodule
require/replaceペアを設定する際には、ファイルによって記述された要件の一貫性を保つために、go mod editおよびgo getコマンドを使用してください。
$ go mod edit -replace=example.com/theirmodule@v0.0.0-unpublished=../theirmodule
$ go get example.com/theirmodule@v0.0.0-unpublished
注:replaceディレクティブを使用する場合、Goツールは依存関係の追加で説明されているように外部モジュールを認証しません。
バージョン番号の詳細については、「モジュールのバージョン番号付け」を参照してください。
独自のリポジトリフォークからの外部モジュールコードの要求
外部モジュールのリポジトリをフォークした場合(モジュールのコードの問題を修正したり、機能を追加したりするためなど)、Goツールにモジュールのソースとしてフォークを使用させることができます。これは、独自のコードからの変更をテストするのに役立ちます。(モジュールを必要とするモジュールと同じローカルドライブ上のディレクトリでモジュールコードを要求することもできることに注意してください。詳細については、ローカルディレクトリ内のモジュールコードの要求を参照してください。)
これは、go.modファイルにreplaceディレクティブを使用して、外部モジュールの元のモジュールパスをリポジトリ内のフォークへのパスに置き換えることで行います。これにより、Goツールはコンパイル時に置換パス(フォークの場所)を使用するよう指示されます。これにより、importステートメントを元のモジュールパスから変更せずに残すことができます。
replaceディレクティブの詳細については、go.modファイルリファレンスを参照してください。
次のgo.modファイルの例では、現在のモジュールは外部モジュールexample.com/theirmoduleを要求しています。次に、replaceディレクティブは元のモジュールパスを、モジュール自体のリポジトリのフォークであるexample.com/myfork/theirmoduleに置き換えます。
module example.com/mymodule
go 1.23.0
require example.com/theirmodule v1.2.3
replace example.com/theirmodule v1.2.3 => example.com/myfork/theirmodule v1.2.3-fixed
require/replaceペアを設定する際には、ファイルによって記述された要件の一貫性を保つためにGoツールコマンドを使用してください。go listコマンドを使用して、現在のモジュールで使用されているバージョンを取得します。次に、go mod editコマンドを使用して、必要なモジュールをフォークに置き換えます。
$ go list -m example.com/theirmodule
example.com/theirmodule v1.2.3
$ go mod edit -replace=example.com/theirmodule@v1.2.3=example.com/myfork/theirmodule@v1.2.3-fixed
注:replaceディレクティブを使用する場合、Goツールは依存関係の追加で説明されているように外部モジュールを認証しません。
バージョン番号の詳細については、「モジュールのバージョン番号付け」を参照してください。
リポジトリ識別子を使用した特定のコミットの取得
go getコマンドを使用して、モジュールのリポジトリ内の特定のコミットからの未公開コードを追加できます。
これを行うには、go getコマンドを使用し、@記号で目的のコードを指定します。go getを使用すると、コマンドはgo.modファイルに、コミットに関する詳細に基づく擬似バージョン番号を使用して外部モジュールを要求するrequireディレクティブを追加します。
次の例は、いくつかの図を示しています。これらは、ソースがgitリポジトリにあるモジュールに基づいています。
-
特定のコミットでモジュールを取得するには、
@コミットハッシュの形式を追加します。$ go get example.com/theirmodule@4cf76c2 -
特定のブランチでモジュールを取得するには、
@ブランチ名の形式を追加します。$ go get example.com/theirmodule@bugfixes
依存関係の削除
コードがモジュール内のどのパッケージも使用しなくなった場合、そのモジュールを依存関係として追跡するのを停止できます。
すべての未使用モジュールの追跡を停止するには、go mod tidyコマンドを実行します。このコマンドは、モジュール内のパッケージをビルドするために必要な不足している依存関係も追加する場合があります。
$ go mod tidy
特定の依存関係を削除するには、go getコマンドを使用し、モジュールのモジュールパスを指定し、次の例のように@noneを追加します。
$ go get example.com/theirmodule@none
go getコマンドは、削除されたモジュールに依存する他の依存関係もダウングレードまたは削除します。
ツールの依存関係
ツールの依存関係を使用すると、Goで記述され、モジュールでの作業中に使用される開発ツールを管理できます。たとえば、stringerをgo generateで使用したり、送信のために変更を準備する際の一部として特定のリンターやフォーマッターを使用したりできます。
Go 1.24以降では、次のようにツール依存関係を追加できます。
$ go get -tool golang.org/x/tools/cmd/stringer
これにより、go.modファイルにtoolディレクティブが追加され、必要なrequireディレクティブが存在することが保証されます。このディレクティブが追加されると、ツールのインポートパスの最後の非メジャーバージョンコンポーネントをgo toolに渡すことでツールを実行できます。
$ go tool stringer
複数のツールが最後のパスフラグメントを共有する場合、またはパスフラグメントがGoディストリビューションに同梱されているツールのいずれかと一致する場合は、代わりに完全なパッケージパスを渡す必要があります。
$ go tool golang.org/x/tools/cmd/stringer
現在利用可能なすべてのツールのリストを表示するには、引数なしでgo toolを実行します。
$ go tool
toolディレクティブをgo.modに手動で追加することもできますが、ツールを定義するモジュールに対するrequireディレクティブが存在することを確認する必要があります。不足しているrequireディレクティブを追加する最も簡単な方法は、次を実行することです。
$ go mod tidy
ツールの依存関係を満たすために必要な要件は、モジュールグラフ内の他の要件と同じように動作します。それらは最小バージョン選択に参加し、require、replace、およびexcludeディレクティブを尊重します。モジュールプルーニングのため、ツール依存関係自体を持つモジュールに依存する場合、そのツール依存関係を満たすためだけに存在する要件は、通常、モジュールの要件にはなりません。
tool メタパターンは、すべてのツールに対して同時に操作を実行する方法を提供します。たとえば、go get -u toolでHツールをすべてアップグレードしたり、go install toolでそれらすべてを$GOBINにインストールしたりできます。
Go 1.24より前のバージョンでは、ビルド制約を使用してビルドから除外されるモジュール内のgoファイルに空白インポートを追加することで、toolディレクティブに似たものを実現できます。これを行うと、完全なパッケージパスを使用してgo runでツールを実行できます。
モジュールプロキシサーバーの指定
Goツールを使用してモジュールを操作する場合、ツールはデフォルトでproxy.golang.org(Googleが運営する公開モジュールミラー)から、またはモジュールのリポジトリから直接モジュールをダウンロードします。Goツールに、代わりに別のプロキシサーバーを使用してモジュールをダウンロードおよび認証するように指定できます。
これは、あなた(またはあなたのチーム)が使用したい別のモジュールプロキシサーバーを設定または選択した場合に行いたいかもしれません。たとえば、一部の人々は、依存関係の使用方法をより細かく制御するためにモジュールプロキシサーバーを設定しています。
Goツールが使用する別のモジュールプロキシサーバーを指定するには、GOPROXY環境変数に1つ以上のサーバーのURLを設定します。Goツールは、指定された順序で各URLを試行します。デフォルトでは、GOPROXYはまずGoogleが運営する公開モジュールプロキシを指定し、次にモジュールのリポジトリからの直接ダウンロード(そのモジュールパスで指定されているとおり)を指定します。
GOPROXY="https://proxy.golang.org,direct"
他の動作をサポートする値を含むGOPROXY環境変数の詳細については、goコマンドリファレンスを参照してください。
変数を他のモジュールプロキシサーバーのURLに設定できます。URLはコンマまたはパイプで区切ります。
-
コンマを使用すると、現在のURLがHTTP 404または410を返した場合にのみ、Goツールはリストの次のURLを試行します。
GOPROXY="https://proxy.example.com,https://proxy2.example.com" -
パイプを使用すると、GoツールはHTTPエラーコードに関係なく、リストの次のURLを試行します。
GOPROXY="https://proxy.example.com|https://proxy2.example.com"
Goモジュールは、パブリックインターネットで利用できないバージョン管理サーバーやモジュールプロキシで頻繁に開発および配布されています。GOPRIVATE環境変数を設定して、goコマンドがプライベートソースからモジュールをダウンロードおよびビルドするように構成できます。これにより、goコマンドはプライベートソースからモジュールをダウンロードおよびビルドできます。
GOPRIVATEまたはGONOPROXY環境変数は、プライベートであり、どのプロキシからも要求すべきではないモジュールプレフィックスに一致するグロブパターンのリストに設定できます。例:
GOPRIVATE=*.corp.example.com,*.research.example.com