[修正済み] go.modのgoディレクティブにパッチバージョンを含めないと「toolchain not available」と怒られる
(2024.4.20 追記)
注意: 将来のGoでは、パッチバージョンを含めなくてもエラーが出なくなる修正が検討されています。
(2024.5.12 追記)
1.21.11
,1.22.4
以降で修正されるようです。
タイトルを解決したい方は、記事を読むよりGoをアップデートしましょう。
現象
Go 1.21以降のgo.mod
内で、go 1.22
のようにパッチバージョンを省略すると goコマンドが失敗します。
$ cat go.mod
module example.com/foo
go 1.22
$ go mod tidy
go: downloading go1.22 (darwin/arm64)
go: download go1.22 for darwin/arm64: toolchain not available
実行例
% GOTOOLCHAIN=local go version
go version go1.21.6 darwin/arm64
解決方法 (兼ベストプラクティス)
go.mod
のgo
ディレクティブに指定するGoバージョンにはパッチバージョンを含めましょう。
go 1.22.0
または、toolchain
ディレクティブを指定しましょう
go 1.22
toolchain go1.22.0
※ 後述しますがtoolchain
ディレクティブはパッチバージョンが省略できないことに注意
問題の深堀り
前提
Go 1.21以降、goコマンドはgo
/toolchain
ディレクティブのバージョン指定を考慮して、よしなにGoツールチェイン[1]をダウンロードし選択するようになりました。
例えば、go 1.22
という行はGo 1.21.Pを許しませんし、toolchain go1.22.1
という行は、Go 1.22.0というツールチェインでビルドすることを許しません。
ここで以下に注意してください。
-
go
とtoolchain
ディレクティブの違い-
go
ディレクティブはGoバージョンを指定する。例:1.22.0
,1.22
,1.22rc1
-
toolchain
ディレクティブはGoツールチェイン名を指定する。例:go1.22.0
-
-
toolchain
が省略された場合、go
ディレクティブで指定したGoバージョンが代わりに使われる
原因
一言で言い切るとしたら以下です。
-
toolchain
ディレクティブを省略すると、代わりにgo
ディレクティブで指定したGoバージョンを使ってツールチェイン名を指定したことになる(toolchain 1.22
)が、ツールチェイン名はパッチバージョンが省略できないのでgoコマンドがツールチェインのダウンロードに失敗する
なので、「解決方法」のようにツールチェイン名にパッチバージョンを与えると解消されます。
1.22
のような省略形が言語バージョンと呼ばれることを考慮すると、今回の現象を次のように言い換えることもできます。
-
go.mod
にtoolchain
を省略してgo
ディレクティブに言語バージョンを指定すると、ツールチェインのダウンロードに失敗する
仕様としてどうなの?
実はこれはバグではなく仕様です。
仕様の是非については、現在issueで突っ込まれています。
意訳すると以下のようなコメントがあります。
-
go
ディレクティブに言語バージョンを指定する場合は、toolchain
ディレクティブを指定すべきことをドキュメントに書くべきでは? - Go 1.21未満では
go 1.20.1
のような記述はできなかったのに、1.21以降ではgo 1.21.0
のような表記が推奨されるのはユーザーの困惑を生んでいそう
異常系としてエラーメッセージを変えてくれると嬉しいですね。
参考
-
Goツールチェインとは、標準ライブラリやコンパイラやツール等もろもろです ↩︎
Discussion