Go Modulesの仕組み Bundler(Ruby)との比較を添えて
by
どすこい
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
Go Modulesの仕組み ~Bundler(Ruby)との⽐較を添えて~ 1 どすこい Fukuoka.go#21
Slide 2
Slide 2 text
2 GMOペパボ Webエンジニア どすこい Daisuke Takeda k1low⽒の弟⼦に習って(=孫弟⼦)、 Goが好きになっちゃったエンジニア 配属先はRails/PHPですが、 そこでもGo⾰命を起こします!! Goコミュニティに参加してくぞ〜! X: @doskoi64
Slide 3
Slide 3 text
PythonやRubyで、 考えなしにパッケージを⼊れると 依存関係解消が失敗することがある... マイナーバージョンアップでも 壊れることある.... ある⽇ イントロダクション 3
Slide 4
Slide 4 text
Railsの場合 イントロダクション 4 Railsガイド https://railsguides.jp/maintenance_policy.html 破壊的変更するんだ...?🤔
Slide 5
Slide 5 text
⼀⽅で Goではあんまり気にしたことないなぁ なんで気にしなくていいんだろ...? ある⽇ イントロダクション 5
Slide 6
Slide 6 text
Go 1.11より イントロダクション 6 https://github.com/golang/go/issues/24301
Slide 7
Slide 7 text
Go 1.11より イントロダクション 7
Slide 8
Slide 8 text
Go 1.11より イントロダクション 8 (前略)、Bundler/Cargo/Depのアプローチの詳 細と、それをGoに組み込むことの意味をより深 く理解し、(中略)、いくつかの細部がGoには適 していないと次第に感じるようになりました。 最初は同じ感じだったんだ? 何が違うんだ?
Slide 9
Slide 9 text
9 今⽇話すこと ● Go Modulesの依存解決の仕組み ● Bundler(Ruby)との⽐較 今⽇話さないこと ● Go Modulesでどこがどう動いてるのか ● Bundlerがどこでどう動いてるのか ● これらの歴史的な経緯
Slide 10
Slide 10 text
Go Modulesの仕組み Go Modulesとは ● Go 1.11から導⼊ ● モジュール:複数のパッケージをまとめてリリース/バージョン管理/配布するための 単位。GitHubやモジュールプロキシサーバからダウンロードが可能 ● モジュールパスによって⼀意に識別してgo.modで宣⾔ ● go.sumにモジュールのハッシュが保持され、ダウンロードしたモジュールの内容が 相違ないかチェック 10 https://go.googlesource.com/proposal/+/master/ design/24301-versioned-go.md ref: Go Modules Reference (https://go.dev/ref/mod)
Slide 11
Slide 11 text
11 Go Modulesの仕組み https://github.com/golang/go/issues/24301 昔はdep, glideなど外部 ツールを⽤いていた。 標準化しようぜ!
Slide 12
Slide 12 text
Go Modulesの仕組み ● go.modに列挙された直接依存から、それぞれが要求す る他の依存(間接依存)を再帰的に集めてビルドリストを 作成 ● 各モジュールでは必要最低限のバージョンを宣⾔ ● これを⽤いてMinimal Version Selection (MVS)で最終 的な依存バージョンを決定 依存解決 12
Slide 13
Slide 13 text
Go Modulesの仕組み ● go.modに記載された直接依存が必要とする依存(間接依 存)を再帰的に収集 ○ 各モジュールは必要最低限なバージョンを指定するた め、すべての依存先から集まった最⼩の要件の中で、 最⼤値となるバージョンが選ばれる ○ module Aではhoge v1.2.3が、module Bでは hoge v1.5.0が要求される時はv1.5.0を採⽤ Minimal Version Selection (MVS) 13
Slide 14
Slide 14 text
Go Modulesの仕組み module Aでhoge v1.2.3が、 module Bでhoge v1.5.0が使われてる→v1.5.0を採⽤ そぼぎ(素朴な疑問) 14 けど、なんでmodule Aでは v1.5.0で動く前提なの?
Slide 15
Slide 15 text
Go Modulesの仕組み module Aでhoge v1.2.3が、 module Bでhoge v1.5.0が使われてる→v1.5.0を採⽤ そぼぎ(素朴な疑問) 15 けど、なんでmodule Aでは v1.5.0で動く前提なの? Semantic Versioningのルールより モジュールパスが同じなら後⽅互換がある! (逆に⾔えばこれが前提のシステム)
Slide 16
Slide 16 text
Go Modulesの仕組み そぼぎ(素朴な疑問) 16 じゃあmodule Aではv1.2.3が、module Bではv2.1.0が 使われてる時、v2.1.0を採⽤するの?(A壊れない?)
Slide 17
Slide 17 text
Go Modulesの仕組み そぼぎ(素朴な疑問) 17 じゃあmodule Aではv1.2.3が、module Bではv2.1.0が 使われてる時、v2.1.0を採⽤するの?(A壊れない?) モジュールパスが異なるv1, v2両⽅採⽤する! ex) gihub.com/oklog/ulidとgithub.com/oklog/ulid/v2 別モジュールとして扱われるので、 v1.2.3とv2.1.0の両⽅をimportすることで 対処できる
Slide 18
Slide 18 text
Go Modulesの仕組み 詳しくはGO Conference2024ののびしーさんの発表があります! 18 https://gocon.jp/2024/sessions/13/
Slide 19
Slide 19 text
Rubyとの⽐較 ● gem の依存関係とバージョンを管理するための ツール ● Gemfileで任意にgemのバージョン を指定できる ○ = のほかに、<=, >などで⼤⼩関係で指定できる Bundler 19
Slide 20
Slide 20 text
Rubyとの⽐較 Gemfileに指定された制約を解析し、 全ての制約を満たすバージョンの 組み合わせを探す ⼤変らしい(NP完全) https://arxiv.org/pdf/2011.07851 (⾼速な解法がないとも⾔えるかも) Bundlerの依存解決アルゴリズム 20
Slide 21
Slide 21 text
Rubyとの⽐較 ● Aでは ○ Cについて”>= 1.0, < 3.0” ● Bでは ○ Cについて”>= 3.0, < 3.5” Bundlerが困る時: 解がないとき 21 最適なバージョンがない場合が発⽣しうる ※ (補⾜) 別gemとして別バージョンを利⽤する⽅法はあるらしい けどGo Modulesはシンプルで⼀意に決まります → 解なし...
Slide 22
Slide 22 text
⽭盾の例 ● Aでは ○ Cについて”>= 1.0, < 3.0” ● Bでは ○ Cについて”>= 3.0, < 3.5” Rubyとの⽐較 なんでGoだとこうならないの? 22 Goでは、C v1.0とC v3.0を 別モジュールとしてimportできる
Slide 23
Slide 23 text
⽭盾の例2 ● Aでは ○ Cについて”>= 1.0, < 1.5” ● Bでは ○ Cについて”>= 1.6, < 2.0” Rubyとの⽐較 なんでGoだとこうならないの? 23
Slide 24
Slide 24 text
⽭盾の例2 ● Aでは ○ Cについて”>= 1.0, < 1.5” ● Bでは ○ Cについて”>= 1.6, < 2.0” Rubyとの⽐較 なんでGoだとこうならないの? 24 Semantic Versioningの後⽅互換の前提があるので マイナーバージョンの上限を指定しないので起こらない → v1.6になる
Slide 25
Slide 25 text
まとめ Go ModulesはSemantiv Versioning を前提に依存関係解消をしている 任意にバージョンを指定できる⾔語の 場合、最適なバージョンをソルバーが 解く必要がある Go Modulesはルールによってシンプル さを獲得した具体例かもしれない 25 今⽇話したこと
Slide 26
Slide 26 text
26 Let’s Go