以下の内容はhttps://christina04.hatenablog.com/entry/mvs-downgradeより取得しました。


go get でアップデートすると、なぜか別のライブラリがダウングレードする

背景

go get でアップデートすると、なぜか別のライブラリがダウングレードする不思議な現象に出会いました。

$ go get github.com/userA/hoge
go: downgraded github.com/userB/foo v1.2.1 => v1.0.0
go: downgraded github.com/userB/bar v1.10.0 => v1.1.0
go: upgraded github.com/userA/hoge v1.4.0 => v1.5.0

環境

Go v1.23.2

原因

原因は

  • GoがMVS(Minimal version selection)を採用している
  • ライブラリが循環参照している

ためでした。

Minimal version selectionとは

MVSはモジュールグラフ全体の依存関係を見て、各モジュールの最小(最も古い)の必要バージョンを使う仕組みです。

ref: https://go.dev/ref/mod#minimal-version-selection

この例で言うと、例えばDはD 1.3が最大バージョンですが、メインモジュールからすると最小の必要バージョンではありません

なので

  • go get -uで全体をアップグレード
  • go get -u D@1.3して個別アップグレード

しない限りはD 1.2が選択されます。

メリット

  • 選択されるバージョンが外部要因(=新しいパッケージのリリース)の影響を受けない
    • 依存関係解決の再現性が保証される
  • パッケージマネージャーの実装がシンプルになる

デメリット

  • 最新バージョンになりにくい
  • 場合によってはダウングレードする(今回のケース)
    • 修正済みのバグを踏む可能性がある

循環参照の影響

上記の図ではライブラリ間の循環参照(相互参照)が無いため問題無いですが、個人ライブラリ等によっては循環参照のある依存関係が生まれているケースがあります。

この場合

A 1.5はB 1.4に依存している
↓
B 1.4はA 1.4に依存している
↓
A 1.4はB 1.3に依存してる
↓
B 1.3はA 1.3に依存してる
↓
...

と巡り巡ってどんどん最低バージョンに遡っていくことが起きます。

解決方法

この状況の場合、ダウングレードしたライブラリをgo getで最新しようとしても、MVSによって循環参照を巡り巡って最低バージョンにされるので解決できません。
なので基本的には以下の方針となります。

  1. 循環参照を無くす
  2. go.modのreplaceでバージョンを固定する

a. 循環参照を無くす

根本解決はこちらになります。
循環参照はライブラリ間の結合を密にしますし、それによって意図しない影響が生まれるので基本的に避けるようにしましょう。

ただ長い間放置されたものだったりすると、修正コストが高くついたりするので緩和対応として次の方針を取ることも良いでしょう。

b. go.modのreplaceでバージョンを固定する

MVSはreplaceを考慮するのでダウングレードが発生しなくなります。

ref: https://go.dev/ref/mod#mvs-replace

replace github.com/userB/foo => github.com/userB/foo v1.2.1
replace github.com/userB/bar => github.com/userB/bar v1.10.0

その他

Maximal Version Selectionとは

Minimal version selectionの反対に、Maximal Version Selectionがあります。
これは

  • 指定されたなかで最大の(=最新の)バージョンを使う。
  • 最大バージョン選択は Bundler, npm 等をはじめとする多くのプログラミング言語のパッケージマネージャで採用されている。

v1.0 以上のバージョンが指定されていて現在の最新バージョンが v1.1 の場合、v1.1 がインストールされます。

まとめ

MVS(Minimal version selection)の説明と、それによって引き起こる期待しない挙動について説明しました。

参考




以上の内容はhttps://christina04.hatenablog.com/entry/mvs-downgradeより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14