📝

`go`ディレクティブ (荒訳)

2022/01/08に公開

goディレクティブについての説明 https://go.dev/ref/mod#go-mod-file-go の荒訳です。


goディレクティブ

goディレクティブは、そのモジュールがどのバージョンのGoのセマンティクスを想定して書かれたかを示します。このバージョンはGoの有効なリリースバージョンで、正の整数にドット及び負ではない整数が続きます。(例: 1.9, 1.14)

goディレクティブはもともとGo言語の後方互換性のない変更(Go 2への移行を参照)をサポートするためのものでした。モジュールが導入されて以来、互換性のない言語の変更は導入されていませんでしたが、goディレクティブは言語の新機能の使用に影響を及ぼします:

  • あるモジュール内のパッケージにおいて、コンパイラはgoディレクティブで指定されたバージョン以降に導入された機能の利用を拒否します。例えばモジュールにgo 1.12ディレクティブがあった場合、そのモジュール内のパッケージではGo 1.13で導入された1_000_000のような数値リテラルは利用できません。
  • 古いバージョンのGoを用いてあるモジュールのパッケージをビルドしコンパイラーエラーに遭遇した場合、そのモジュールはより新しいバージョンのGoに向けて書かれたことがエラーメッセージからわかります。例えばあるモジュールにgo 1.13ディレクティブが書かれ、数値リテラル1_000_000を使っている場合に、そのパッケージをGo 1.12でビルドしようとするとコンパイラはコードがGo 1.13用に書かれていることを知らせてくれます。

加えてgoコマンドはgoディレクティブに書かれたバージョンに基づいてその振る舞いを変えます。具体的には以下のような影響があります:

  • go 1.14以降では、自動ベンダリングが有効になる場合があります。vendor/modules.txtファイルが存在しgo.modと整合性がとれていれば、明示的に-mod=vendorフラグを与える必要はなくなります。
  • go 1.16以降では、allパッケージパターンはメインモジュール (訳注: goコマンドが実行されたモジュール)のパッケージやテストから推移的にインポートされるパッケージにのみマッチします。これはモジュールが導入されて以来go mod vendorで取得できるパッケージのセットと同じです。より古いバージョン(訳注: たぶんgo 1.15以前)ではallはメインモジュールのパッケージによりインポートされるパッケージのテストや、それらのパッケージのテストなどもすべて含まれています。
  • go 1.17以降では以下の影響があります:
    • go.modファイルに、メインモジュール内のパッケージ及びテストにより推移的にインポートされるパッケージを提供するモジュールのための明示的なrequireディレクティブを1つ含みます。(go 1.16以前では最小限バージョン選択戦略において最小ではないバージョンを選択される際に間接的な依存(indirect dependency)として含まれます。)この追加情報はモジュールグラフの刈り込みモジュールの遅延読み込みを実現するのに使われます。
    • goの以前のバージョンよりも多くの// indirectな依存が含まれる場合があるので、間接的依存はgo.modファイル内の独立したブロックに記録されます。
    • go mod vendorコマンドはgo.modgo.sumファイルをベンダーされた依存モジュールについては省略します。(これにより、vendorディレクトリ内のサブディレクトリでgoコマンドを実行した際に、正しいメインモジュールを特定できるようなります。)
    • go mod vendorコマンドは、ベンダーされた依存モジュール内のgo.modファイルに記載されたgoディレクティブのバージョンをvendor/modules.txtに記録します。

1つのgo.modファイルは最大1個のgoディレクティブを含められます。ほとんどのコマンド(訳注: おそらくgo modコマンドのサブコマンドのこと)はgo.modファイルにgoディレクティブが含まれていなかった場合に現在のGoのバージョンでgoディレクティブを追加します。

GoDirective = "go" GoVersion newline .
GoVersion = string | ident .  /* valid release version; see above */

例:

go 1.14

訳者メモ

コンパイルに使うgoコマンドのバージョンよりも新しいバージョンがgoディレクティブ記載されていても即座にエラーになるわけではないことに留意が必要です。つまりgo 1.13と書かれたモジュールであってもgo 1.13固有の記法やスタンダードパッケージや機能を使っていないならば、Go 1.12でビルドできます。

Discussion