Goブログ
Go 1.16 での新しいモジュール変更
Go 1.16 を楽しんでいただければ幸いです!このリリースには、特にモジュールに関して多くの新機能があります。 リリースノートでこれらの変更について簡単に説明していますが、いくつか詳しく見ていきましょう。
モジュールがデフォルトで有効
go
コマンドは、go.mod
が存在しない場合でも、デフォルトでモジュール認識モードでパッケージをビルドするようになりました。これは、すべてのプロジェクトでモジュールを使用するための大きな一歩です。
GO111MODULE
環境変数を off
に設定することで、GOPATH モードでパッケージをビルドすることも引き続き可能です。また、GO111MODULE
を auto
に設定して、現在のディレクトリまたは親ディレクトリに go.mod ファイルが存在する場合にのみモジュール認識モードを有効にすることもできます。これは以前はデフォルトでした。GO111MODULE
およびその他の変数は、go env -w
で永続的に設定できることに注意してください。
go env -w GO111MODULE=auto
Go 1.17 では GOPATH モードのサポートを終了する予定です。言い換えれば、Go 1.17 は GO111MODULE
を無視します。モジュール認識モードでビルドしないプロジェクトがある場合は、今すぐ移行する時です。移行を妨げる問題がある場合は、issue または 体験レポートの提出を検討してください。
go.mod および go.sum の自動変更なし
以前は、go
コマンドが go.mod
または go.sum
に、不足している require
ディレクティブや不足している sum などの問題を発見した場合、自動的に問題を修正しようとしていました。特に通常は副作用のない go list
のようなコマンドでは、この動作が驚くべきものであるという多くのフィードバックを受けました。自動修正が常に望ましいとは限りませんでした。インポートされたパッケージが必須モジュールによって提供されていない場合、go
コマンドは新しい依存関係を追加し、共通の依存関係のアップグレードをトリガーする可能性がありました。スペルミスのあるインポートパスでさえ、(失敗した)ネットワークルックアップにつながります。
Go 1.16 では、モジュール認識コマンドは、go.mod
または go.sum
の問題を発見した後、自動的に問題を修正しようとする代わりにエラーを報告します。ほとんどの場合、エラーメッセージは問題を修正するためのコマンドを推奨します。
$ go build
example.go:3:8: no required module provides package golang.org/x/net/html; to add it:
go get golang.org/x/net/html
$ go get golang.org/x/net/html
$ go build
以前と同様に、go
コマンドは vendor
ディレクトリが存在する場合は使用する可能性があります (詳細については ベンダーリングを参照してください)。go get
や go mod tidy
などのコマンドは、主な目的が依存関係を管理することであるため、go.mod
と go.sum
を引き続き変更します。
特定のバージョンで実行可能ファイルをインストールする
go install
コマンドは、@version
サフィックスを指定することで、特定のバージョンで実行可能ファイルをインストールできるようになりました。
go install golang.org/x/tools/gopls@v0.6.5
この構文を使用する場合、go install
は、現在のディレクトリと親ディレクトリにある go.mod
ファイルを無視して、その正確なモジュールバージョンからコマンドをインストールします。(@version
サフィックスがない場合、go install
はこれまでと同様に動作し続け、現在のモジュールの go.mod
にリストされているバージョン要件と置き換えを使用してプログラムをビルドします。)
以前は、go get -u program
を使用して実行可能ファイルをインストールすることをお勧めしていましたが、この使用法では、go.mod
のモジュールバージョン要件を追加または変更するための go get
の意味と混乱が生じすぎていました。また、go.mod
を誤って変更することを避けるために、人々は次のようなより複雑なコマンドを提案し始めました。
cd $HOME; GO111MODULE=on go get program@latest
これで、代わりに go install program@latest
を使用できるようになりました。詳細については、go install
を参照してください。
使用されるバージョンに関するあいまいさをなくすために、このインストール構文を使用する場合、プログラムの go.mod
ファイルに存在する可能性のあるディレクティブにはいくつかの制限があります。特に、replace
および exclude
ディレクティブは、少なくとも今のところ許可されていません。長期的には、新しい go install program@version
が十分なユースケースでうまく機能するようになったら、go get
がコマンドバイナリのインストールを停止するように計画しています。詳細については、issue 43684 を参照してください。
モジュールの取り消し
準備ができる前に誤ってモジュールバージョンを公開したことはありますか?または、バージョンを公開した直後に、迅速に修正する必要がある問題を発見したことはありますか?公開されたバージョンでの間違いは修正が困難です。モジュールビルドを決定論的に保つために、バージョンは公開後に変更することはできません。バージョンタグを削除または変更した場合でも、proxy.golang.org
やその他のプロキシは、おそらく元のキャッシュを既に持っています。
モジュールの作成者は、go.mod
の retract
ディレクティブを使用してモジュールバージョンを取り消すことができるようになりました。取り消されたバージョンは引き続き存在し、ダウンロードできます (したがって、それに依存するビルドは壊れません) が、go
コマンドは @latest
などのバージョンを解決する際に自動的に選択することはありません。go get
および go list -m -u
は、既存の使用に関する警告を出力します。
たとえば、人気のあるライブラリ example.com/lib
の作成者が v1.0.5
をリリースし、その後、新しいセキュリティ問題を発見したとします。作成者は、以下のようなディレクティブを go.mod
ファイルに追加できます。
// Remote-triggered crash in package foo. See CVE-2021-01234.
retract v1.0.5
次に、作成者は新しい最高バージョンであるバージョン v1.0.6
にタグを付けてプッシュできます。この後、v1.0.5
に既に依存しているユーザーは、更新を確認したり、依存パッケージをアップグレードしたりすると、取り消しについて通知されます。通知メッセージには、retract
ディレクティブの上のコメントからのテキストを含めることができます。
$ go list -m -u all
example.com/lib v1.0.0 (retracted)
$ go get .
go: warning: example.com/lib@v1.0.5: retracted by module author:
Remote-triggered crash in package foo. See CVE-2021-01234.
go: to switch to the latest unretracted version, run:
go get example.com/lib@latest
インタラクティブなブラウザベースのガイドについては、モジュールバージョンの取り消し を play-with-go.dev で確認してください。構文の詳細については、retract
ディレクティブドキュメントを参照してください。
GOVCSを使用したバージョン管理ツールの制御
go
コマンドは、proxy.golang.org のようなミラーから、または git
、hg
、svn
、bzr
、または fossil
を使用してバージョン管理リポジトリから直接モジュールソースコードをダウンロードできます。特にプロキシで利用できないプライベートモジュールの場合、直接バージョン管理アクセスは重要ですが、セキュリティ上の問題になる可能性もあります。バージョン管理ツールのバグは、悪意のあるサーバーによって意図しないコードを実行するために悪用される可能性があります。
Go 1.16 では、新しい構成変数である GOVCS
が導入されました。これにより、ユーザーは特定のバージョン管理ツールを使用できるモジュールを指定できます。GOVCS
は、pattern:vcslist
ルールのコンマ区切りリストを受け入れます。pattern
は、モジュールパスの1つ以上の先頭要素に一致する path.Match
パターンです。特別なパターン public
および private
は、パブリックおよびプライベートモジュールに一致します (private
は GOPRIVATE
のパターンに一致するモジュールとして定義され、public
はその他すべてです)。vcslist
は、許可されたバージョン管理コマンドのパイプ区切りリストか、キーワード all
または off
です。
例えば
GOVCS=github.com:git,evil.com:off,*:git|hg
この設定では、github.com
のパスを持つモジュールは git
を使用してダウンロードできます。evil.com
のパスは、どのバージョン管理コマンドを使用してもダウンロードできず、他のすべてのパス (*
はすべてに一致) は git
または hg
を使用してダウンロードできます。
GOVCS
が設定されていない場合、またはモジュールがどのパターンにも一致しない場合、go
コマンドは次のデフォルトを使用します。git
および hg
はパブリックモジュールに対して許可され、すべてのツールはプライベートモジュールに対して許可されます。GitとMercurialのみを許可する理由は、これら2つのシステムが信頼できないサーバーのクライアントとして実行される問題に最も注意を払ってきたためです。対照的に、Bazaar、Fossil、およびSubversionは主に信頼できる認証済み環境で使用されており、攻撃対象として十分に精査されていません。つまり、デフォルト設定は次のとおりです。
GOVCS=public:git|hg,private:all
詳細については、GOVCS
を使用したバージョン管理ツールの制御を参照してください。
次は?
これらの機能がお役に立てば幸いです。私たちはすでに Go 1.17 の次のモジュール機能、特にモジュール読み込みプロセスをより高速で安定させる 遅延モジュール読み込みに取り組んでいます。いつものように、新しいバグが発生した場合は、issue tracker でお知らせください。ハッピーコーディング!
次の記事:コンテキストと構造体
前の記事:Go 1.16 がリリースされました
ブログインデックス