In Go 1.24, I propose to make rand.Seed (the top-level function) a no-op, controlled by GODEBUG=randseednop=1. (Because it is GODEBUG-controlled, specific programs could opt back to the old behavior using a //go:debug line, through Go 1.27 at least.)

The rationale is that rand.Seed is already deprecated, but it is preventing math/rand users from getting more secure randomness by default. There exist imported packages that call rand.Seed(time.Now().UnixNano()) “just in case”, and that makes math/rand fall back to the old Go 1 generator.

There no doubt exist some programs that use rand.Seed correctly for a reproducible simulation or the like, with only one goroutine at a time using the randomness, and being careful not to call any standard library or other packages that themselves contain even a single call to rand.Int or any other top-level function. It is possible, but it is fragile. (This is the same argument we made to auto-seed and deprecate Seed in the first place.)

Those programs can do what we said back then: instead of rand.Seed(s), use r := rand.New(rand.NewSource(s)) and pass r around. They can even name the variable rand to minimize code updates. They can even:

import mathrand "math/rand"
var rand = mathrand.New(mathrand.NewSource(seed))

Making those already-fragile programs convert to this form will remove the fragility, and it will let us fix the majority case of programs that don't care about reproducibility but are getting the insecure Go 1 generator when they could instead be getting the secure ChaCha8 generator.

If Go 1.28 retired the GODEBUG (following our “minimum four release” policy for GODEBUGs), then at that point we could make math/rand's top-level functions trivial wrappers around math/rand/v2's top-level functions, making them eligible for gofix to update. (Note that Go 1.28 would not arrive until the year 2027 - this is very much playing the long game.)

Comment From: apparentlymart

I am tangentially responsible for a codebase that does use fixed seeding to produce reproducible random numbers, and so I was initially concerned by this proposal, but I see that it's talking specifically about the global rand.Seed and would not affect the ability to instantiate a source with a specified seed.

That seems very reasonable to me. Expecting the shared global source to have a predictable seed, even though literally anything in the program could reseed it at any time, seems like an unreasonable expectation.


The current docs for rand.Seed promise that one can call rand.Seed(1) to achieve behavior from older versions of Go. Would that promise somehow be kept, e.g. by treating the argument 1 differently than other values? Or do you think it's defensible to break that contract? (I don't have any strong opinion either way)

Prior to Go 1.20, the generator was seeded like Seed(1) at program startup. To force the old behavior, call Seed(1) at program startup. Alternately, set GODEBUG=randautoseed=0 in the environment before making any calls to functions in this package.

Comment From: rsc

I am tangentially responsible for a codebase that does use fixed seeding to produce reproducible random numbers, and so I was initially concerned by this proposal, but I see that it's talking specifically about the global rand.Seed and would not affect the ability to instantiate a source with a specified seed.

Indeed. I added "global" to the title. Thanks for pointing out the potential confusion.

The current docs for rand.Seed promise that one can call rand.Seed(1) to achieve behavior from older versions of Go. Would that promise somehow be kept, e.g. by treating the argument 1 differently than other values? Or do you think it's defensible to break that contract? (I don't have any strong opinion either way)

No, the promise would be broken, just with a 2+ year grace period. We already broke the promise for what happens when you don't seed, so it's the same promise, broken twice.

Comment From: rsc

This proposal has been added to the active column of the proposals project and will now be reviewed at the weekly proposal review meetings. — rsc for the proposal review group

Comment From: rsc

Have all remaining concerns about this proposal been addressed?

The proposal details are in https://github.com/golang/go/issues/67273#issue-2288189812.

Comment From: rsc

Based on the discussion above, this proposal seems like a likely accept. — rsc for the proposal review group

The proposal details are in https://github.com/golang/go/issues/67273#issue-2288189812.

Comment From: rsc

No change in consensus, so accepted. 🎉 This issue now tracks the work of implementing the proposal. — rsc for the proposal review group

The proposal details are in https://github.com/golang/go/issues/67273#issue-2288189812.

Comment From: gopherbot

Change https://go.dev/cl/606055 mentions this issue: math/rand: make calls to Seed no-op

Comment From: gopherbot

Change https://go.dev/cl/696135 mentions this issue: arm64/arm64asm: stop relying on global rand.Seed