Go モジュールと依存関係
チュートリアルの続きをしようと思ったら、パッケージの依存関係のエラーに遭遇してしまい(原因不明)。Goのパッケージ管理について学習しました。
今までの背景を振り返ってみる
Go get パッケージ名
指定パッケージのGitリモートリポジトリを$GOPATH/srcへダウンロード
依存関係のGitリモートリポジトリを$GOPATH/srcへダウンロード
普通に利用すると以下の状態になる。
- $GOPATHは一つ
- go getでは常に最新バージョンを取得する
以下のような課題を持つ
プロジェクトA -> 外部パッケージ(1.0)
プロジェクトB -> 外部パッケージ(1.0)
*外部パッケージは誰かが作った、オープンソースのイメージです。
プロジェクトBの外部パッケージを1.0 → 1.1にしたい
go get 外部パッケージ
プロジェクトA -> 外部パッケージ(1.1)
プロジェクトB -> 外部パッケージ(1.1)
プロジェクトBだけの更新ができない。
dep
プロジェクト個別に依存関係のパッケージのバージョン管理ができない。
ここでdepを利用する。(vendoringもありましたが割愛します)
- Gopkg.lockファイル:
利用しているパッケージの最新バージョンの一覧情報的なもの。どんなパッケージに依存しているかわかりやすい - Gopkg.tomlファイル:
利用しているパッケージのバージョンを固定する。最新を取得しないように制限
上記のファイルでバージョンを管理すれば、明示的にプロジェクトないしパッケージ毎にバージョンを管理できるようになった。
まだ一番重要な課題が残っている!
プロジェクトは一旦一つとして考える。
自作モパッケージA -> 外部パッケージA(1.0) -> 外部パッケージB(1.0).funcX()
自作モパッケージB -> 外部パッケージB(1.0)
この状態で自作パッケージBの方で、外部パッケージのバージョンを1.0 → 1.1に更新したい。
ここで、外部パッケージB(1.1)で外部パッケージA(1.0)から呼んでいたfuncX()が削除されてしまったら問題が発生しそうです。
どう解決された?(vgo)
まだ正式リリースではないので、色々課題は残っていると思いますが
go1.1からvgoが公開されました。
go1.1ではmoduleという概念が増えています。
vgoのバージョン管理はセマンティックを採用しています。
セマンティック バージョニング
詳しくはこちら
個人的に重要なポイントだなと思ったのは以下
セマンティック バージョニングを適用するソフトウェアはパブリックAPIを宣言しなければなりません
moduleという概念でバージョンを定義する。
moduleの一番嬉しいポイントとしては、以下に書く、依存関係の問題を解消する手段ができたなのかなと思っています。
*他に大きなメリットを知っている方がいましたら、教えて頂けると嬉しいです。
細かいバージョンの切り方についてはまだ踏み込んでいないのですが、
少なくとも、各パッケージ毎に自分が呼んでいるパッケージとそのバージョンを持つようになります。
上記によって以下が解決される(自作パッケージBが呼んでいる、外部パッケージBのバージョンのみ変更可能)
自作モパッケージA -> 外部パッケージA(1.0) -> 外部パッケージB(1.0).funcX()
自作モパッケージB -> 外部パッケージB(1.1)
また、セマンティックバージョンをみんなが意識することで、外部パッケージをどのバージョンまで上げて良いのかがわかるようになります。
バージョン番号x.y.z
xを変更すると、後方互換性を保っていません。→動作保証しません
となるので、先ほどの例だと1.y系は更新のリスクが低いが、2.y系は心してテストするか修正を伴うということがわかるようになります。
感想的なもの
vgoの適用タイミングは各プロダクトの状況に合わせてになると思います。
Javaの経験が長いのですが、恥ずかしながら、勉強不足かつ業務未使用というのもあり、moduleについては触れてこなかったため、このタイミングで少しだけ比較をイメージしてみました。
Javaでも同じような問題を抱えていると思います。(OSS、J2EEなど巨大なので根が深い?)
mavenなどでバージョンの管理はできるけど、depと同じような状況なのかなと。
JDK9でmoduleの概念が導入されているが、Javaの場合は、依存性管理については切り離すという方向性のようです。vgoのようにモジュール毎に依存関係のバージョンを持たない。
Javaは11になっても、この問題を解決するには苦労するのかなと思ったりすると、ちょっと頭が・・
モジュール対応も半ば強制的に対応させられるような形で大きな変更が入っていますが、使い所がイマイチ見えておりません。
最後に、実装して確認するまでの時間が取れなかったので、想像で書いているところもあります。視野がまだ狭くてmoduleの概念について理解できていないところもあると思います。