see the [runtime documentation](/pkg/runtime#hdr-Environment_Variables)
and the [go command documentation](/cmd/go#hdr-Build_and_test_caching).
+### Go 1.24
+
+Go 1.24 changed the global [`math/rand.Seed`](/pkg/math/rand/#Seed) to be a
+no-op. This setting is controlled by the `randseednop` setting.
+For Go 1.24 it defaults to `randseednop=1`.
+Using `randseednop=0` reverts to the pre-Go 1.24 behavior.
+
### Go 1.23
Go 1.23 changed the channels created by package time to be unbuffered
--- /dev/null
+Calls to the deprecated top-level [Seed] function no longer have any effect. To
+restore the old behavior set `GODEBUG=randseednop=0`. For more background see
+the proposal [#67273](/issue/67273).
{Name: "netedns0", Package: "net", Changed: 19, Old: "0"},
{Name: "panicnil", Package: "runtime", Changed: 21, Old: "1"},
{Name: "randautoseed", Package: "math/rand"},
+ {Name: "randseednop", Package: "math/rand", Changed: 24, Old: "0"},
{Name: "tarinsecurepath", Package: "archive/tar"},
{Name: "tls10server", Package: "crypto/tls", Changed: 22, Old: "1"},
{Name: "tls3des", Package: "crypto/tls", Changed: 23, Old: "1"},
var randautoseed = godebug.New("randautoseed")
+// randseednop controls whether the global Seed is a no-op.
+var randseednop = godebug.New("randseednop")
+
// globalRand returns the generator to use for the top-level convenience
// functions.
func globalRand() *Rand {
// a random value. Programs that call Seed with a known value to get
// a specific sequence of results should use New(NewSource(seed)) to
// obtain a local random generator.
+//
+// As of Go 1.24 [Seed] is a no-op. To restore the previous behavior set
+// GODEBUG=randseednop=0.
func Seed(seed int64) {
+ if randseednop.Value() != "0" {
+ return
+ }
+ randseednop.IncNonDefault()
+
orig := globalRandGenerator.Load()
// If we are already using a lockedSource, we can just re-seed it.
}
}
+func TestSeedNop(t *testing.T) {
+ // If the global Seed takes effect, then resetting it to a certain value
+ // should provide predictable output to functions using it.
+ t.Run("randseednop=0", func(t *testing.T) {
+ t.Setenv("GODEBUG", "randseednop=0")
+ Seed(1)
+ before := Int63()
+ Seed(1)
+ after := Int63()
+ if before != after {
+ t.Fatal("global Seed should take effect")
+ }
+ })
+ // If calls to the global Seed are no-op then functions using it should
+ // provide different output, even if it was reset to the same value.
+ t.Run("randseednop=1", func(t *testing.T) {
+ t.Setenv("GODEBUG", "randseednop=1")
+ Seed(1)
+ before := Int63()
+ Seed(1)
+ after := Int63()
+ if before == after {
+ t.Fatal("global Seed should be a no-op")
+ }
+ })
+ t.Run("GODEBUG unset", func(t *testing.T) {
+ Seed(1)
+ before := Int63()
+ Seed(1)
+ after := Int63()
+ if before == after {
+ t.Fatal("global Seed should default to being a no-op")
+ }
+ })
+}
+
// Benchmarks
func BenchmarkInt63Threadsafe(b *testing.B) {
The number of non-default behaviors executed by the math/rand
package due to a non-default GODEBUG=randautoseed=... setting.
+ /godebug/non-default-behavior/randseednop:events
+ The number of non-default behaviors executed by the math/rand
+ package due to a non-default GODEBUG=randseednop=... setting.
+
/godebug/non-default-behavior/tarinsecurepath:events
The number of non-default behaviors executed by the archive/tar
package due to a non-default GODEBUG=tarinsecurepath=...