
はじめに
Go1.24 リリース連携の7本目です。
Go Modules におけるツール管理の進化について取り上げます。
アップデートサマリ
- Go Modules で go.mod に
tool
ディレクティブが追加になったgo get -tool
でtool
ディレクティブに指定されたパッケージを追加できるgo get tool
でツールのアップデートや、go install tool
でツールのインストール、go tool hoge
でツールの実行ができる、など- インストールした実行ファイルは、Goのビルドキャッシュにキャッシュされる
アップデートのモチベーションなど(#48429)
歴史的経緯
Goでアプリケーションを実装するときに、Goのツールを使って開発することはよくあります。Goのツールの例として、たとえばや fmt.Stringer
インターフェースを満たすコードを生成する Stringer や SQL から Go のコードを生成できる sqlc などが挙げられるでしょう。
チーム開発するうえでツールのバージョン管理は重要です。チーム内で同じバージョンのツールを使って開発できることが望ましく、別バージョンを利用していると開発者間で不要な差分や、動作しないソースがリポジトリにコミットされてしまう可能性などが考えられます。
Go1.24の本機能がリリースされる以前は、主に以下の方法でツールのバージョン管理が行われていました。このあたりのノウハウは Go Wiki の How can I track tool dependencies for a module? にまとまっています。
tools.go
を利用する方法go install
でバージョンを指定する方法
tools.go を利用する方法
go install
でツールのバイナリをインストールできましたが、Go 1.15 以前ではインストール時にバージョン指定ができませんでした。インストール時に go.mod にバージョンが追記されますが、どこからも import されていない場合 go mod tidy
で依存関係が削除されてしまいます。そこで Build Constraints
を利用するテクニックが知られています。ブランクインポートにより import されているが、Build Constraints
でコンパイル/ビルドはされないようにしています。Build Constraints
を利用する Go のファイル例の記載例は以下のようなものです。ファイル名は慣習として tools.go
とすることが多いでしょう。
// +build tools |
go install でバージョンを指定する方法
Go 1.16 からは go install
でインストール時にバージョン指定できるようになりました。このリリースにより go.mod の依存関係に影響を与えず、ツールをインストールできるようになりました。このあたりの話は、過去のGo1.16のリリース連携記事(Go 1.16のgo installについて)でも触れています。
余談ですが、私たちのチームでは go install
でバージョン指定してインストールするコマンドを Makefile などにまとめて記載することがよくあります。
|
提案のモチベーション
tools.go
や go install
を利用したプラクティスは Go の開発者にはよく知られています。ただ Go Modules によるバージョン管理のサポートとしては比較的弱い、Go で書かれたツール周りの開発者体験を向上させたい、というのが #48429 や Proposal:Adding tool dependencies to go.mod で述べられています。
試してみた
導入された新機能のうち、ツールの追加、バージョンの更新、ツールの実行のそれぞれを試してみます。なお、Goバージョンは go 1.24rc2
です。
空の go.mod
に github.com/sqlc-dev/sqlc/cmd/[email protected]
をツールとして追加します。
module sample |
go get -tool github.com/sqlc-dev/sqlc/cmd/[email protected]
します。
> go get -tool github.com/sqlc-dev/sqlc/cmd/[email protected] |
コマンドを実行すると go.mod
の tool
ディレクティブに github.com/sqlc-dev/sqlc/cmd/sqlc
が追加されており、バージョンが require
で管理されていることがわかります。バージョンは v1.27.0
が入っていますね。
module sample |
また go get tool
でツールのバージョンを最新化(v1.27.0
→ v1.28.0
)してみます。
> go get tool |
go.mod
を確認すると、たしかにバージョンが2025/01/23現在の最新である v.1.28.0
に更新されていることがわかります。
module sample |
また go install tool
で $GOBIN
(デフォルトで $GOPATH/bin
) にバイナリがインストールされていることも確認できました。これで go.mod で管理しているツールをまとめてインストールできます。
ツールは go tool sqlc
として実行できました。なお $GOBIN
へのパスが通っていれば、go tool
コマンドなしで sqlc
としても実行できます。
> go tool sqlc |
まとめ
go.mod
の tool
ディレクティブの追加により、ツールのバージョン管理がシンプルにできるようになりました。Makefile などによるインストールスクリプトや tools.go
のテクニックが不要になる日も近いかもしれません。