メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

新機能

math/rand/v2のRandにジェネリックメソッドNを追加し、トップレベル関数Nと同じ使い勝手をカスタムRandインスタンスでも実現した。

math/rand/v2

この項目の注釈は AI により生成されており、誤りを含む場合があります。
使用例のコンパイル検証: 検証済み

概要

math/rand/v2Rand型に、ジェネリックメソッドNが追加された。任意の整数型に対応するトップレベル関数Nと同じ挙動を、カスタムの*Randインスタンス上でも利用できるようになる。

導入経緯

math/rand/v2パッケージ設計当時のGoにはジェネリックメソッドという言語機能が存在せず、トップレベルのジェネリック関数Nに対応するRandのメソッド版を追加できなかった。そのためRand型にはIntNInt64NUint32Nなど型ごとの個別メソッドしか用意されておらず、カスタムソースを使う場合は型に応じてメソッドを使い分ける必要があった。

Goにジェネリックメソッドを追加する提案(#77273)が受理されたことを受け、その帰結として本提案が2026-05-06にIssue #77853として起票された。

議論タイムライン

  • 2026-05-06: Proposal Review Meeting(aclements, adonovan, bradfitz, cherrymui, griesemer, neild, rolandshoemaker)で明確な反対意見がなく、likely acceptと判定された。
  • 2026-05-07: 実装CL(go.dev/cl/775100)が提出された。
  • 2026-05-13: 反対意見が出ないまま正式にacceptedとなった。

議論のハイライト

  • 既存のトップレベル関数N(デフォルトのグローバルソースを使用)と、カスタムソースを持つ*Rand型との間で使い勝手に非対称性があったことが、追加の主な動機である。
  • 本提案はGo言語へのジェネリックメソッド追加(#77273)が実装されることを前提としており、Issue本文でも「#77273実装後に追加する」と明示されていた。
  • 新規メソッドの追加であるため、既存コードへの後方互換性への影響はない。

使用例

Before

package main

import (
	"fmt"
	"math/rand/v2"
	"time"
)

func main() {
	r := rand.New(rand.NewPCG(1, 2))
	n64 := r.Int64N(100)
	dur := time.Duration(r.Int64N(int64(5 * time.Second)))
	fmt.Println(n64, dur)
}

After

package main

import (
	"fmt"
	"math/rand/v2"
	"time"
)

func main() {
	r := rand.New(rand.NewPCG(1, 2))
	n64 := r.N(int64(100))
	dur := r.N(5 * time.Second)
	fmt.Println(n64, dur)
}

実装解説

実装はsrc/math/rand/v2/rand.go;l=213(r *Rand) N[Int intType](n Int) Intで、n <= 0ならpanicし、内部のuint64nを呼んで結果を型パラメータIntにキャストして返すだけの薄いラッパーになっている。これはトップレベル関数N(src/math/rand/v2/rand.go;l=336)がグローバルなRandインスタンス経由で同じロジックを呼び出しているのと同型の実装であり、型制約intType(src/math/rand/v2/rand.go;l=340)も両者で共有されている。

関連リンク