𝗣𝗮𝗰𝗸𝗮𝗴𝗲.𝗷𝘀𝗼𝗻 𝘃𝘀 𝗴𝗼.𝗺𝗼𝗱: バージョンフィールドはどこへ消えたのか?

JavaScriptからGoに移行すると、あることに驚かされるでしょう。

package.jsonファイルを開いてみてください。一番上にversionフィールドがあるのがすぐにわかります。読みやすく、プルリクエスト内で変更することも可能です。それはコードの中に存在しています。

次に、go.modファイルを開いてみましょう。

そこにはバージョンがありません。これは間違いではなく、一つの選択なのです。

Goは、自身のモジュールに対してバージョンフィールドを使用しません。代わりにgitタグを使用します。

仕組み: • git tag v1.2.3 を実行する • タグをリポジトリにプッシュする • そのタグがあなたのバージョンになります

誰かが go get を実行すると、Goは適切なコミットを見つけるためにgitタグを確認します。タグが「信頼できる唯一の情報源(single source of truth)」となります。

この設計には大きな強みがあります。バージョンが誤ったコードを指すことが決してないということです。npmでは、公開されたコードとバージョンフィールドが乖離してしまうことがあります。しかしGoでは、それらは同一のものです。バージョンとは、コミットそのものなのです。

ただし、これによりワークフローが変わります:

例: v1 は github.com/you/my-app を使用 v2 は github.com/you/my-app/v2 を使用

これにより、一つのプログラムが同じライブラリの異なる2つのメジャーバージョンを、競合することなく使用できるようになります。

他のほとんどの言語は、ファイル内にバージョンを保持しています: • Node: package.json • Rust: Cargo.toml • Python: pyproject.toml • Java: pom.xml

Goは例外です。gitタグに厳格に依存しています。

npmのような体験が恋しい場合は、ビルド時に ldflags を使用してバイナリにバージョンを注入することができます。これにより、アプリのバージョン確認コマンドに対応させることが可能です。

トレードオフは単純です: バージョンフィールドは読みやすくレビューもしやすいですが、嘘をつく可能性があります。 gitタグは見えにくいですが、常に真実です。

Goは利便性よりも真実を選んだのです。

Goの開発者の皆さんへ:これは最善のモデルでしょうか?もしツールがgitタグと照合して検証してくれるのであれば、go.modにバージョンフィールドがある方が良いと思いますか?

出典: https://dev.to/dalirnet/packagejson-vs-gomod-where-did-the-version-field-go-3301