依存関係の管理

コードが外部パッケージを使用する場合、それらのパッケージ(モジュールとして配布)は依存関係になります。時間の経過とともに、それらをアップグレードまたは置き換える必要がある場合があります。Goは、外部依存関係を組み込む際にGoアプリケーションを安全に保つのに役立つ依存関係管理ツールを提供します。

このトピックでは、コードで引き受ける依存関係を管理するためのタスクを実行する方法について説明します。これらのほとんどはGoツールで実行できます。このトピックでは、役立つ可能性のある他のいくつかの依存関係関連タスクを実行する方法についても説明します。

こちらも参照してください

依存関係を使用および管理するためのワークフロー

Goツールを使用して、便利なパッケージを入手して使用できます。pkg.go.devでは、便利なパッケージを検索し、goコマンドを使用してそれらのパッケージを自分のコードにインポートして、その関数を呼び出すことができます。

以下に、最も一般的な依存関係管理の手順を示します。それぞれ詳細については、このトピックのセクションをご覧ください。

  1. pkg.go.dev便利なパッケージを見つける
  2. コードで使用するパッケージをインポートする
  3. 依存関係を追跡するために、コードをモジュールに追加します(モジュールにまだない場合)。依存関係の追跡を有効にするをご覧ください。
  4. 外部パッケージを依存関係として追加することで、それらを管理できるようにします。
  5. 必要に応じて、時間の経過とともに依存関係のバージョンをアップグレードまたはダウングレードする

モジュールとしての依存関係の管理

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は、次の文字列がパッケージ名で使用されないことを保証します。

依存関係の追加

公開されたモジュールからパッケージをインポートしたら、go getコマンドを使用して、そのモジュールを依存関係として管理するように追加できます。

コマンドは次のことを行います

以下にいくつかの例を示します。

コマンドは、ダウンロードする各モジュールも認証します。これにより、モジュールが公開されたときから変更されていないことが保証されます。モジュールが公開されてから変更された場合(たとえば、開発者がコミットの内容を変更した場合)、Goツールはセキュリティエラーを表示します。この認証チェックは、改ざんされている可能性のあるモジュールから保護します。

特定の依存関係バージョンの取得

go getコマンドで依存関係モジュールのバージョンを指定することにより、特定の依存関係モジュールバージョンを取得できます。コマンドは、go.modファイルのrequireディレクティブを更新します(ただし、手動で更新することもできます)。

これは次の場合に行うとよいでしょう

以下に、go getコマンドの使用例を示します。

次のgo.modファイルのrequireディレクティブの例(詳細については、go.modリファレンスを参照してください)は、特定のバージョン番号を要求する方法を示しています。

require example.com/theirmodule v1.3.4

利用可能な更新の発見

現在のモジュールで使用している依存関係のより新しいバージョンがあるかどうかを確認できます。go list コマンドを使用して、モジュールの依存関係のリストと、そのモジュールで利用可能な最新バージョンを表示します。利用可能なアップグレードを発見したら、コードで試して、新しいバージョンにアップグレードするかどうかを決定できます。

go list コマンドの詳細については、go list -m を参照してください。

いくつかの例を以下に示します。

依存関係のアップグレードまたはダウングレード

Goツールを使用して利用可能なバージョンを検出し、異なるバージョンを依存関係として追加することで、依存関係モジュールをアップグレードまたはダウングレードできます。

  1. 新しいバージョンを見つけるには、利用可能な更新の発見で説明されているように、go list コマンドを使用します。

  2. 特定のバージョンを依存関係として追加するには、特定の依存関係バージョンの取得で説明されているように、go get コマンドを使用します。

コードの依存関係の同期

コードのインポートされたすべてのパッケージの依存関係を管理すると同時に、インポートしなくなったパッケージの依存関係を削除できます。

これは、コードと依存関係に変更を加えた結果、管理された依存関係とダウンロードされたモジュールのコレクションが、コードにインポートされたパッケージで特に必要なコレクションと一致しなくなった可能性がある場合に役立ちます。

管理された依存関係セットを整理しておくには、go mod tidy コマンドを使用します。このコマンドは、コードにインポートされたパッケージのセットを使用して、不足しているが必要なモジュールをgo.modファイルに追加します。また、関連するパッケージを提供しない未使用のモジュールも削除します。

このコマンドには、削除されたモジュールに関する情報を出力する -v フラグ以外に引数はありません。

$ go mod tidy

未公開のモジュールコードに対する開発とテスト

コードが公開されていない可能性のある依存関係モジュールを使用するように指定できます。これらのモジュールのコードは、それぞれのリポジトリ、それらのリポジトリのフォーク、またはそれらを使用する現在のモジュールのあるドライブにある可能性があります。

これは、次のような場合に役立ちます。

ローカルディレクトリのモジュールコードを要求する

必要なモジュールのコードが、それを必要とするコードと同じローカルドライブ上にあるように指定できます。これは、次のような場合に役立ちます。

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 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モジュールは、多くの場合、パブリックインターネットでは利用できないバージョン管理サーバーとモジュールプロキシで開発および配布されます。GOPRIVATE 環境変数を設定して、go コマンドがプライベートソースからモジュールをダウンロードおよびビルドするように構成できます。すると、goコマンドはプライベートソースからモジュールをダウンロードしてビルドできます。

GOPRIVATE または GONOPROXY 環境変数は、プライベートであり、プロキシから要求されるべきではないモジュールプレフィックスに一致するグロブパターンのリストに設定できます。例えば

GOPRIVATE=*.corp.example.com,*.research.example.com