math/rand/v2: add Rand.N
要約
概要
math/rand/v2 パッケージには、任意の整数型に対してジェネリクスを使用した N 関数が既に存在しますが、rand.Rand 型に対応するメソッド Rand.N がありません。本提案は、Go言語においてジェネリックメソッドが承認された(#77273)ことを受けて、Rand.N メソッドを math/rand/v2 に追加するものです。
ステータス変更
**** → likely_accept
2026年5月6日のProposal Review Meeting(@aclements, @adonovan, @bradfitz, @cherrymui, @griesemer, @neild, @rolandshoemaker)にて、明確な反対意見がなく議論が収束していたことから「likely accept」に移行しました。Rand.N の追加は #77273(ジェネリックメソッドの言語仕様追加)の自然な帰結であり、既存の N 関数との一貫性を保つものとして評価されています。
技術的背景
現状の問題点
math/rand/v2 が作成された当時、Go言語はジェネリックメソッドをサポートしていませんでした。そのため、Rand 型にはジェネリックな N メソッドを追加できず、代わりに型ごとに個別のメソッドが存在します(IntN、Int32N、Int64N、UintN など)。この結果、Rand オブジェクトを使ったコードではトップレベルの N 関数の恩恵を受けられず、型変換が必要な場面が残っていました。
// 問題: カスタムRandオブジェクトを使う場合、型ごとのメソッドしかない
r := rand.New(rand.NewPCG(seed1, seed2))
// time.Duration型の乱数を得るために明示的な型変換が必要
d := time.Duration(r.Int64N(int64(5 * time.Second)))
提案された解決策
Rand 型にジェネリックメソッド N を追加します。
// N returns a pseudo-random number in the half-open interval [0,n).
// The type parameter Int can be any integer type.
// It panics if n <= 0.
func (r *Rand) N[Int intType](n Int) Int
この intType は math/rand/v2 内部で定義されたすべての整数型を含む制約で、int、int32、int64、uint、uint32、uint64 などが対象です。
これによって何ができるようになるか
カスタムの乱数ジェネレータ(rand.Rand インスタンス)を使用する場合でも、トップレベルの N 関数と同様にジェネリクスを活用した簡潔な乱数生成が可能になります。型変換の記述が不要になり、コードが読みやすくなります。
コード例
// Before: カスタムRandオブジェクトを使う場合、型ごとのメソッドと明示的な型変換が必要
r := rand.New(rand.NewPCG(seed1, seed2))
// time.Duration型のランダムな待機時間
d := time.Duration(r.Int64N(int64(5 * time.Second)))
// ランダムなインデックス(int型)
idx := r.IntN(len(items))
// After: Rand.N メソッドでジェネリクスを使い、型変換が不要
r := rand.New(rand.NewPCG(seed1, seed2))
// time.Duration型のランダムな待機時間(型推論で自動的にDuration型)
d := r.N(5 * time.Second)
// ランダムなインデックス(型推論でint型)
idx := r.N(len(items))
議論のハイライト
- ジェネリックメソッドの言語サポートが前提条件: 本提案は #77273(Go言語へのジェネリックメソッド追加)が承認・実装されることを前提としており、依存関係が明示されています。
math/rand/v2設計当時はジェネリックメソッドが「将来的にも実現不可能」とされていたため、意図的に除外されていました。 - API一貫性の確保: トップレベルの
N関数とRand.Nメソッドの対称性が保たれることで、デフォルトのグローバルRandを使う場合とカスタムRandを使う場合とでコードスタイルを統一できます。 - 後方互換性: 新規メソッドの追加であるため、既存コードへの影響はありません。
gabyhelpが関連issueとして #61716(math/rand/v2 revised API)と #63880(IntInRange関数提案)を挙げていますが、本提案はより限定的でシンプルな追加です。- 実装タイミング: #77273 の実装完了後に対応予定であり、Go本体のジェネリックメソッド実装の進捗に依存します。