焼売飯店

GoとかTS、JSとか

Go 1.24で入ったGo製ツールの管理機能が便利だったのでおすすめしたい

Go 1.24の新機能で、Go製ツールのバージョンをGo Modulesで管理できるようになったので、その概要と便利なポイントを紹介していきます。

これまでのGo製ツールのバージョン管理について

これまで、Go製ツールのバージョンを管理する方法として標準的なものはありませんでした。

そのため、仕方なく直接 go install github.com/XXX/cmd/ツール名@バージョン をコマンドとして打たざるを得ないシーンが多々ありました。(過去の方法については今回あまり深堀りしません)

これからのGo製ツールのバージョン管理について

Go 1.24からGo組み込みの機能として提供される新しいツール管理方法は、従来のものよりずっと手軽になっています。

使い方が非常に簡単なので、ここで紹介する内容はGo以外のプロジェクトでも使えると思っています。Go Modulesを既存のプロジェクトに同居させる必要はありますが、それを特に気にしない方にはおすすめできます。

本記事では基本的な使い方についてのみ紹介します。詳しく知りたい方は以下のujiさんの記事などをご覧ください。(※ujiさんの記事執筆時点ではGo 1.24は未リリースでしたが、本記事の執筆時点ではリリース済みとなります)

zenn.dev

使い方

Go製ツールのバージョン管理は、Go Modulesの機能の一部として提供されるため、まずはプロジェクトのルートでGo Modulesの初期化を行います。

go mod init

続いて、必要なツールを取得します。 例として、筆者の作った絵文字を検索するためのemoというツールを入れてみます。

go get -tool github.com/syumai/emo/cmd/emo

バージョンを明示したい場合は、ツール名の後ろに @バージョン を付けて実行します。

go get -tool github.com/syumai/emo/cmd/emo@v0.2.2

あとは、プロジェクト配下で以下のように呼び出すだけでインストールしたツールを使うことができます。

go tool emo

新しいツール管理機能の何がいいのか?

この機能のいいところをいくつか挙げてみます。

  • 標準の機能である
  • Go Modulesの機能である
  • ツールを明示的にインストールしなくていい

標準の機能である

まず、この機能はGo標準の機能なので、サードパーティのツールを導入する必要がありません。必要なのはGoだけです。Goさえインストールされていれば動きます。

Go Modulesの機能である

この機能はGo Modulesの提供する機能の一部でしかないので、既存の仕組みを流用できます。たとえば、DependabotやRenovateによってツールの更新を自動で行えます

また、あるGoのモジュールを、ライブラリとして使い、コマンドとしても使うようなケースで、必ずこれら2つのバージョンが揃うようにできます。ライブラリ側とコマンド側のバージョンが合わなくて面倒になるケースがたまにあるので、地味に助かります。

ツールを明示的にインストールしなくていい

Go Modulesで管理されているツールを go tool ツール名 で実行する際に、明示的なインストール操作は不要で、自動的にインストールが走ります。これがかなり便利です。誰かが事前に go get -tool でツールをGo Modules管理下に追加する必要はありますが、既存のチームメンバーのツール導入コストや、新メンバー加入時のオンボーディングコストを減らしてくれると思います。

また、Go Modulesで管理されているツールのバージョンが更新されていたら、手元のツールを明示的にインストールし直さなくても更新されます。例えば、もともと手元で使っていた emo@v0.2.0 をDependabotが emo@v0.2.1 に更新していたとしたら、手元の emo はインストールし直さなくても勝手に v0.2.1 になります。

不便な点

個人的には非常に満足していますが、go tool のPrefixが実行に必要となるのでたまに取り回しに困ります。

例えば、protocのプラグインは、特定の名前のパターンのコマンドを期待していて、Goのコードを生成する用のプラグインはprotoc-gen-goとなっています。 protoc-gen-goはGo製のツールなので、Go Modulesで管理したくなりますが、実行に go tool のPrefixが必要になるとうまく組み合わせて使えません。

protocのケースに関してだけ言うと、Twitterで紹介されていた、Bufを使う手法で回避できました。

しかしながら、絶妙にユースケースを満たさないような場合もあるかもしれません(あまり想像はついていないですが)

最後に

非常に便利なので、個人的には積極的に使っていきたいと思っています。

Go製のツール以外のバージョンの管理も合わせて行いたいような場合はaquaなどを使った方がいいケースもあると思います。当然ですが、必ずGo Modulesを使った方がいいとまでは思っていません。

これくらい手軽に使える方法であれば、Go製ツールのバージョン管理のためだけに、Go以外のプロジェクトでも使ってみていいのではないでしょうか?賛否が分かれるかもしれませんが、例えば、npm scriptsに go tool ツール名 を直接書いてもいいと思っています。よかったら、Twitterなどで感想をお待ちしています。