go.modのgo directiveとtoolchain directive
go.modのgo directiveは「このモジュールをビルドするのに必要なGoの最小バージョン」を宣言するもの。一方toolchain directiveは「開発時に実際に使うツールチェーンのバージョン」を指定するもので、両者は役割が違う。
go 1.24.0
toolchain go1.25.5
go directiveを最新にしてしまうと何が起きるか
前提として、Goは半年ごとにメジャーリリースされ(例: 2025年は1.24と1.25)、公式サポートは新しい2つのメジャーリリースのみ(詳細はGoのリリースサイクルとサポートポリシー)。
ライブラリやツールのgo.modでgo directiveを最新メジャーリリース(例: go 1.25.5)にしてしまうと:
- 1つ前のメジャーリリース(まだ公式サポート内)を使っているユーザーがそのモジュールをビルドできなくなる。
godirectiveの要求は依存元にも伝播する。あるライブラリがgo 1.25.5を宣言すると、それに依存するモジュールもGo 1.24をサポートできなくなる。- Go 1.24で入ったtool directive経由のツール依存でも同じことが起きる(arthur-1氏の記事ではGoReleaserが例に挙げられている)。
推奨される書き方(OSSのライブラリ・ツールの場合)
godirectiveは1つ前のメジャーリリースにする。最新が1.25ならgo 1.24.0。- パッチバージョンは
.0にする。パッチを上げて宣言すると、ユーザー側がマイナーアップデートでバグ対応する余地を狭めるため。 - 開発で最新の言語機能やツールチェーンを使いたい場合は
toolchaindirectiveで別途指定する。これでビルドの下限(go directive)と実際に使うツールチェーンを分離でき、GitHub Actionsのsetup-goなどでも正しいバージョンが使われる。 - デメリットは「最新メジャーリリースで入った言語機能をライブラリ本体のコードですぐ使えない」ことだが、半年後の次リリースで使えるようになる。
Go 1.26からはgo mod initが生成するgo directiveのデフォルトが1つ前のメジャーリリースになる予定で、Goチーム自身もこの方針を推奨しているとのこと。
Goの開発ツーリングの中での位置づけ
モジュール管理系。リリースポリシーを前提に、ライブラリのgo.modをどう書くべきかという方針の話。