Description
Previously, #25988 was put on hold, because API changes to x/exp/rand
where hold off on. I'm running into the same problem right now. I would assume that over the last three years the decision of whether or not we want to change math/rand
for Go 2 has manifested a bit more.
My proposal is less of an API change. Instead of adding a NewLockedSource
function, I'd suggest to change LockedSource.src
from a pointer into a value. The methods on LockedSource
have pointer-receivers, so we'd still be able to call pointer-methods on it. This would both make src.Seed
work on a zero-value LockedSource
and remove a pointer indirection.
The reasons I want to use a LockedSource
are the same as @krancour mentions in the above issue:
The standard library puts us between a rock and a hard place, forcing us to choose:
- Concurrency safety (by using math/rand package level functions), but risk the shared
Source
being stupidly re-seeded by other code with a value like 1.- A seeded
Source
that you know for sure hasn't been / cannot be stupidly re-seeded by other code (i.e. not math/rand package levelSource
), but is not concurrency safe.
That is exactly the trade-off I've run into a couple of times now. For now, I'll probably use a package-scoped sync.Pool
, but it would be great if we could just get a package-scoped, concurrency-safe *rand.Rand
.
Also, I think if we don't add either a constructor or do something like this proposal, we should remove LockedSource
again. There is no benefit to exporting a type which can't be used.