依存関係の管理
コードが外部パッケージを使用する場合、それらのパッケージ(モジュールとして配布)は依存関係になります。時間の経過とともに、それらをアップグレードまたは置き換える必要がある場合があります。Goは、外部依存関係を組み込む際にGoアプリケーションを安全に保つのに役立つ依存関係管理ツールを提供します。
このトピックでは、コードで引き受ける依存関係を管理するためのタスクを実行する方法について説明します。これらのほとんどはGoツールで実行できます。このトピックでは、役立つ可能性のある他のいくつかの依存関係関連タスクを実行する方法についても説明します。
こちらも参照してください
- モジュールとしての依存関係の操作に不慣れな場合は、簡単な紹介として入門チュートリアルをご覧ください。
go
コマンドを使用して依存関係を管理すると、要件の一貫性が保たれ、go.modファイルの内容が有効であることが保証されます。コマンドのリファレンスについては、Command goをご覧ください。go help mod tidy
のように、コマンドラインでgo help
command-nameと入力してヘルプを表示することもできます。- 依存関係の変更を行うために使用する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>
-
prefixは、通常、モジュールの出所などを記述する文字列など、モジュールを部分的に記述する文字列です。これは、次のいずれかになります
-
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.16
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.16
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
を使用すると、コマンドは、コミットの詳細に基づく疑似バージョン番号を使用して、外部モジュールを必要とする require
ディレクティブをgo.modファイルに追加します。
次の例は、いくつかの例を示しています。これらは、ソースが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ツールを使用してモジュールを操作する場合、ツールはデフォルトで、proxy.golang.org(Googleが運営する公開モジュールミラー)またはモジュールのリポジトリからモジュールを直接ダウンロードします。代わりに、Goツールがモジュールのダウンロードと認証に別のプロキシサーバーを使用するように指定できます。
これは、あなた(またはあなたのチーム)が使用したい別のモジュールプロキシサーバーを設定または選択した場合に役立ちます。たとえば、依存関係の使用方法をより詳細に制御するために、モジュールプロキシサーバーを設定する人もいます。
Goツールで使用する別のモジュールプロキシサーバーを指定するには、GOPROXY
環境変数を1つ以上のサーバーのURLに設定します。Goツールは、指定した順序で各URLを試行します。デフォルトでは、GOPROXY
は最初にGoogleが運営する公開モジュールプロキシを指定し、次にモジュールのリポジトリ(モジュールパスで指定されている)から直接ダウンロードします。
GOPROXY="https://proxy.golang.org,direct"
他の動作をサポートする値を含む GOPROXY
環境変数の詳細については、go
コマンドリファレンスを参照してください。
変数を他のモジュールプロキシサーバーのURLに設定できます。URLはコンマまたはパイプで区切ります。
-
コンマを使用すると、Goツールは、現在のURLがHTTP 404または410を返した場合にのみ、リスト内の次の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