Slide 1

Slide 1 text

標準パッケージに uuid が追加された 背景から見る Go らしい意思決定 2026/09/11 Go Conference 2026 @convto

Slide 2

Slide 2 text

whoami @convto (よみは「こんぶと」です) LayerX所属 (2023-03 -) バクラク事業部 アカウント基盤開発部 IDチーム 2023-09 くらいから ID 基盤の開発に関わっています © LayerX Inc.

Slide 3

Slide 3 text

はじめに このセッションの対象 uuid に興味がある人 広く使われるソフトウェアのデザインにまつわる議論に興味がある人 Go を書いたことがない人も歓迎です! © LayerX Inc. 3

Slide 4

Slide 4 text

はじめに このセッションで話すこと 広く使われるソフトウェアの課題や、それに対する Go のアプローチ uuid がどのような経緯で追加されるに至ったか uuid 実装にあたってデザイン面でどのような議論があったか © LayerX Inc. 4

Slide 5

Slide 5 text

広く使われるソフトウェアの難しさ

Slide 6

Slide 6 text

広く使われるソフトウェアの難しさ 広く使われるソフトウェアは何に困るのか 利用者が増えるほど、あらゆる挙動が依存される 公開したものを変えることはこれらの依存を壊すことであり、広く使われるほど影響も 大きい (なんなら linkname の話とかは公開すらしていない) © LayerX Inc. 6

Slide 7

Slide 7 text

広く使われるソフトウェアの難しさ Go 互換性ポリシー Goは極力互換性を保つことで、Goで書かれたプログラムが壊れることを避けている Go1 で書かれたコードは将来の Go1 系リリースが登場しても例外を除き引き続き動作する: https://go.dev/doc/go1compat Go1 の互換性を破壊するような Go2 は永遠にない https://go.dev/blog/compat 利用者への恩恵は非常に大きい が、実装側は公開したAPIの互換に保ち続けるコストを負う © LayerX Inc. 7

Slide 8

Slide 8 text

広く使われるソフトウェアの難しさ 例: net/http に残る context 以前の API context パッケージの導入以前、キャンセル制御は個別の仕組みだった その頃の仕組みは今も後方互換として net/http に残り続けている より良い仕組みが生まれても、一度公開したものは消せない ref: https://pkg.go.dev/net/[email protected]#CloseNotifier © LayerX Inc. 8

Slide 9

Slide 9 text

広く使われるソフトウェアの難しさ 標準ライブラリへの追加は長期的なコストを伴う 標準パッケージや言語仕様を追加すると 互換性を維持し続ける 必要がある このコストに見合うリターンがなければ追加しない、という判断になる © LayerX Inc. 9

Slide 10

Slide 10 text

広く使われるソフトウェアの難しさ FAQ: Why isn't X in the standard library? 標準ライブラリの実装における制約はFAQにも言及がある。 Go 1 互換性保証の対象 になるため、よりよい API を思いついても過去に公開したもの は修正できない Go のリリーススケジュールに縛られ、バグ修正をすぐユーザーに届けられなくなる ほとんどの新しいコードは標準の外に置くべき(リリースサイクル・互換性についての 意思決定を独立してやれる) ref: https://go.dev/doc/faq#x_in_std © LayerX Inc. 10

Slide 11

Slide 11 text

広く使われるソフトウェアの難しさ まとめ: 広く使われるソフトウェアの難しさ 広く使われるソフトウェアは、あらゆる挙動に依存が生まれ、変更が難しくなる Go は Go 1 互換性ポリシーで利用者を守っている。一度公開したものは消せない そのため標準ライブラリへの追加は長期的なコストを伴い、見合うリターンがなければ 追加しない © LayerX Inc. 11

Slide 12

Slide 12 text

uuid を標準に追加する議論の歴史

Slide 13

Slide 13 text

uuid を標準に追加する議論の歴史 前提: UUID ざっくり最小知識 128 bit の識別子で、RFCによって定義されてる v4 など特定のバージョンは広く利用されている こういうやつ -> 4756d853-62af-4c7e-98c6-b49a82250ba9 © LayerX Inc. 13

Slide 14

Slide 14 text

uuid を標準に追加する議論の歴史 #23789 proposal: add uuid generator to stdlib (2018-02) 外部パッケージや独自実装で uuid が作られているので、標準で作ってもいいのではと いう提案 議論ののち Russ Cox が判断材料が不足しているとして却下 I don't think we have enough information about what is needed in the standard library. I think for now the answer is to keep using third-party packages. — rsc, golang/go#23789 クローズ時のコメント ref: https://github.com/golang/go/issues/23789 © LayerX Inc. 14

Slide 15

Slide 15 text

uuid を標準に追加する議論の歴史 再掲: 標準ライブラリの実装にはさまざまな制約がある Go 1 互換性保証の対象 になるため、よりよい API を思いついても過去に公開したもの は修正できない Go のリリーススケジュールに縛られ、バグ修正をすぐユーザーに届けられなくなる ほとんどの新しいコードは標準の外に置くべき(リリースサイクル・互換性についての 意思決定を独立してやれる) ref: https://go.dev/doc/faq#x_in_std © LayerX Inc. これらを打ち消すメリットや普遍性がないと標準には採用されない 15

Slide 16

Slide 16 text

uuid を標準に追加する議論の歴史 再提案: #62026 uuid: add API to generate and parse UUID (2023-08) 2023-08、あらためて uuid の標準ライブラリ追加が提案された これは最終的に accept され Go1.27 で実装された ref: https://github.com/golang/go/issues/62026 2018では判断材料不足としていたが、状況はどう変わったのか © LayerX Inc. 16

Slide 17

Slide 17 text

変化① エコシステムでの実績 Go パッケージの被依存数ランキング 順位 パッケージ 依存モジュール数 1 github.com/stretchr/testify 259,237 2 github.com/google/uuid 104,877 3 golang.org/x/crypto 100,633 4 google.golang.org/grpc 97,228 5 github.com/spf13/cobra 93,062 依存モジュールは 2026-01 時点の proxy.golang.org の内容から分析したよう ref: https://blog.thibaut-rousseau.com/blog/the-most-popular-go-dependency-is/ © LayerX Inc. 17

Slide 18

Slide 18 text

変化① エコシステムでの実績 google/uuid がめちゃめちゃ使われてることがわかった google/uuid は Go エコシステムで 2 番目に import されるパッケージになっていた golang.org/x/crypto や google.golang.org/grpc よりも多い 多くの利用実績があるため、利用傾向を分析したりすることが可能に ref: https://blog.thibaut-rousseau.com/blog/the-most-popular-go-dependency-is/ これにより何をサポートするか、どのようなAPIがよいか、などの 議論がしやすい状態に © LayerX Inc. 18

Slide 19

Slide 19 text

変化② 仕様の成熟 RFC 9562 (2024): UUID 仕様自体もアップデートされた RFC 4122 を置き換える新仕様。v6〜v8 が追加され、仕様が整理された 「どのバージョンを・どうサポートすべきか」を議論するための土台が整った © LayerX Inc. 19

Slide 20

Slide 20 text

uuid を標準に追加する議論の歴史 uuid を標準に追加する議論の歴史 2018 年の提案 #23789 は「判断材料の不足」を理由に却下された 5 年後の再提案 #62026 は accept され、Go 1.27 で実装された 判断を変えた状況の変化は、google/uuid の利用実績と、RFC 9562 による仕様の成熟 © LayerX Inc. 20

Slide 21

Slide 21 text

標準で uuid を持つ意義

Slide 22

Slide 22 text

標準で uuid を持つ意義 標準で実装する意義は実は proposal ではあまり議論されていない proposal 内では「標準に入るとどれだけ嬉しいか」の議論はあまりされていない すでに述べたように再検討できる状況にはなったが、どれくらい嬉しいかはあまり明に整理されていない 再検討始まってわりとすぐにデザインの話になっている ここでは、標準に入って嬉しいことを個人的な目線でまとめることを試みます © LayerX Inc. 22

Slide 23

Slide 23 text

標準で uuid を持つ意義 広く使われているからこそ、標準化の恩恵も大きい 前セクションの通り、uuid は Go エコシステムでかなり頻繁に利用されていた 信頼できるメンテナがメンテナンスを継続してくれるだけで価値がある Go1互換ポリシーから、利用側は安心して使える © LayerX Inc. 23

Slide 24

Slide 24 text

標準で uuid を持つ意義 database/sql との統合 uuid パッケージを追加した CL は、database/sql 側の型変換にもパッチを当てている © LayerX Inc. 24

Slide 25

Slide 25 text

標準で uuid を持つ意義 database/sql との統合 Go 1 互換性ポリシーから database/sql 側も安心して対応できる © LayerX Inc. 25

Slide 26

Slide 26 text

標準で uuid を持つ意義 セキュリティ面の恩恵もちょっとある satori/go.uuid にて、乱数の読み込み処理の不備により 生成される UUID v4 の空間が 狭まる 脆弱性 (CVE-2021-3538) などが起きた セッション ID などに UUID を使っていたら問題 v4 の安全性は「暗号学的に安全な乱数で埋まっていること」が前提 rand の取り扱いを間違えると、偏りが生まれるなど推測余地のある状態になる このような取り回しのミスは言語仕様をよく知る人間がメンテすれば起きづらい © LayerX Inc. 26

Slide 27

Slide 27 text

標準で uuid を持つ意義 CVE-2021-3538 の間違い方 の Read は、エラーを返さずに要求より少ないバイト数だけ読むことがある 読み込みバイト数を確認していなかったため、想定よりも少ない ramdom しか取れて いないケースがあった io.Reader © LayerX Inc. ref: https://github.com/satori/go.uuid/commit/75cca531ea763666bc46e531da3b4c3b95f64557 27

Slide 28

Slide 28 text

標準で uuid を持つ意義 標準で uuid を持つ意義 広く使われているものは、信頼できる標準実装が存在すると恩恵がある database/sql との統合のような、標準同士でなければ取れない手段がある 実装を誤ると発生しうる諸問題も相対的に起きづらい © LayerX Inc. 28

Slide 29

Slide 29 text

その他デザインの議論

Slide 30

Slide 30 text

デザインの各論について この proposal の議論はコメント 400 件超で、論点も多岐にわたる 本セッションでは、その中から発表者が気になったものを取り上げて紹介 前提として思い出したいのが、冒頭で触れた Go 1 互換性ポリシー 一度公開したものは取り下げられない どの論点も、この強い制約を前提に議論されている © LayerX Inc. 30

Slide 31

Slide 31 text

最終的な API の着地をざっと見る 生成・パースがメインの小さな API version / timestamp などの抽出 API は無い © LayerX Inc. 31

Slide 32

Slide 32 text

論点: パッケージ配置 当初案は crypto/uuid で crypto/rand による安全な乱数生成を名前で示そうとした しかし RFC 9562 には暗号にまつわる語彙がほぼ登場しない また将来、乱数ベースでないバージョンをサポートする可能性もある 最終的にトップレベルの uuid に着地 © LayerX Inc. 32

Slide 33

Slide 33 text

サポート範囲について: v4 と v7 だけサポート google/uuid の利用統計を分析してサポート範囲を決定 version v4 v1 v7 その他 利用率 94.17% 4.39% 1.22% 0.22% 判断 サポート ✘ RFC 9562 が新規利用に非推奨 サポート(v1 の後継として推奨) ✘ 利用傾向などを分析した上で、十分利用されるものに絞ってサポート エコシステムで十分な実験がなされたおかげでこのような議論ができた! © LayerX Inc. 33

Slide 34

Slide 34 text

補足: v4 と v7 のレイアウトと特徴 v4: ver / var 以外の 122 bits がすべてランダム random_a 48 bits v7: 先頭 48 bits が UNIX タイムスタンプ(ミリ秒) unix_ts_ms 48 bits ver random_b var 4 12 bits 2 random_c ver rand_a var rand_b 4 12 bits 2 62 bits 62 bits v4: 実質すべてランダムな、推測できない大きな乱数。もっとも広く使われている v7: 先頭がタイムスタンプなので時系列にソートできる。局所性がほしい用途向き © LayerX Inc. 34

Slide 35

Slide 35 text

論点: 作成するときの API はどんな形にするか と NewV4 は現在同じ挙動。それでも両方置くのは version を気にせず単に uuid が ほしいケースを意識 New 将来より良いデフォルトが現れたら、 New の挙動を変えるなども検討できる NewRandom © LayerX Inc. などの意味のある命名も考えられたが v7 に相当する名前が難しく断念 35

Slide 36

Slide 36 text

論点: v7 実装どうするか RFC 9562 では v7 における同一 tick 内の単調性保証の手法を実装者の裁量に委ねている 前回採番したタイムスタンプをプロセス内に保持し、前回以下なら前回値 +1 を採用 秒単位の大きなクロック逆行時は補正しない(そこまでは保証しない割り切り) 詳細まとめたので気になる方はこちらをどうぞ Go1.27 Release Party の資料 unix_ts_ms 48 bits ver 4 sub-ms ts var 12 bits 2 rand_b(毎回ランダム) 62 bits ms 48 + sub-ms 12 をひとつの 60 bit タイムスタンプとして扱う。rand_b はカウンタに使わない © LayerX Inc. 36

Slide 37

Slide 37 text

論点: UUID の中身を覗けるべきか version / timestamp などの抽出 API は提供しない RFC 9562 の「UUID は不透明な値として扱うべき」という推奨に沿った設計 たとえば v7 だとタイムスタンプなど取り出したくなりがち しかし、のちに v4 も利用するようになったら期待する値が取れなくなる、などありうる v7 のレイアウト unix_ts_ms 48 bits © LayerX Inc. ver 4 rand_a 12 bits var 2 rand_b 62 bits 37

Slide 38

Slide 38 text

論点: 時刻を指定して v7 を生成できるべきか 「時刻やオフセットを指定した v7 生成」の要望もあったが 見送り 時系列ソートできることが v7 の重要な点。任意時刻を作れたりオフセット指定可能に すると、その恩恵の一部が崩れる © LayerX Inc. 38

Slide 39

Slide 39 text

論点: Parse は何を受け入れるべきか 当初案は最頻のhexとハイフン形式のみ しかし google/uuid は幅広いパターンをパース可能だった 移行などを考え同様のパターンをサポートすることに © LayerX Inc. 39

Slide 40

Slide 40 text

論点: Nil と Max は必要か RFC 9562 定義の全ビット 0 / 全ビット 1 の UUID 当初は入れない意向だった Nil は UUID{} と書けば済むため は uuid.UUID{} より書き手の意図が伝わるという議論があった 一方を採用するなら対称性のためもう一方も採用しよう、となり両方サポート (個人的には使ったことないので不要と思っているが、まあメンテナンスのコストもほぼ なかろうと思うのでメリットの方が多いと判断されたと理解している) uuid.Nil © LayerX Inc. 40

Slide 41

Slide 41 text

デザインの議論 パッケージ配置からサポート範囲、API の形まで、さまざまな観点で議論された 利用統計や実コードの調査など、サードパーティーの先行があったからこそできた意思 決定も多い エコシステムでの知見が標準に還元された 一度公開したら取り下げられない前提のもと、最小限に絞る判断が多い © LayerX Inc. 41

Slide 42

Slide 42 text

まとめ

Slide 43

Slide 43 text

まとめ まとめ 広く使われるソフトウェアは変更すると影響が大きく、変えづらい Goは例外を除き後方互換を保つ強いポリシーがある 言語仕様や標準パッケージの追加は将来のメンテナンスが必要 Go1.27から標準パッケージに uuid が追加されるが、長く議論されてきた 標準に追加することはデメリットもある。十分なメリットはあるか 追加するとして十分価値のあるもの、変更に強いもののみにする uuid 自体簡素な仕様だが、これらのことを念頭に入れて十分議論の上で実装された © LayerX Inc. 43

Slide 44

Slide 44 text

まとめ まとめ これらの姿勢は、自分が他のプログラムから利用されるようなソフトウェアを書くとき 参考にできる 規模は違うが、より広く使われて多くの価値が提供できるようなソフトウェアを書いて いきたいですね © LayerX Inc. 44

Slide 45

Slide 45 text

ご清聴ありがとうございました