Description
We could rename globalRand
to GlobalRand
now, and drop the package methods (e.g. rand.ExpFloat64
) as part of Go 2.
The benefits I see to making the default instance public are:
-
Maintainers would get a simpler implementation (eventually). The backing code has 83 lines invested in the exposure itself, which we could drop in a stroke at Go 2. And while the tests seem to generally use local
Rand
instances, at least one benchmark has decided to use the global function.Before Go 2, the additional maintainer load seems small (a one-off
s/globalRand/GlobalRand/
inrand.go
and time to write up the godoc comment for the newGlobalRand
. -
Users who don't need multiple
Rand
would gain the ability to pass the public global instance into functions that took aRand
argument and structures that take aRand
property. Checking in the Go corpus v0.1, shows 163 such functions:go-corpus-0.01 $ (cd src && for DIR in . * github.com/*; do echo -n "${DIR}: "; grep -r '^func .*rand\.Rand' "${DIR}" | wc -l; done) | grep -v ' 0$' .: 163 github.com: 146 go.uber.org: 1 golang.org: 8 google.golang.org: 1 k8s.io: 7 github.com/CodisLabs: 1 github.com/attic-labs: 19 github.com/aws: 1 github.com/boltdb: 2 github.com/coreos: 1 github.com/cznic: 1 github.com/docker: 5 github.com/dropbox: 1 github.com/ethereum: 18 github.com/gonum: 26 github.com/gravitational: 1 github.com/hashicorp: 1 github.com/hyperledger: 7 github.com/influxdata: 2 github.com/kelseyhightower: 1 github.com/miekg: 2 github.com/onsi: 2 github.com/openshift: 13 github.com/openzipkin: 1 github.com/oschwald: 1 github.com/pingcap: 15 github.com/prometheus: 6 github.com/streadway: 2 github.com/syndtr: 13 github.com/yudai: 4
-
Everyone gets a simpler API once we hit Go 2 and can drop the package-level methods. Currently the math/rand docs are a longer read than they need to be because each
Rand
method is documented in two places.
Potential drawbacks include:
-
Increased exposure for folks who miss the need to seed their generator if they want different values (lots of discussion in math/rand: Deterministic random by default is dangerous #11871), because they would be able to stuff an unseeded global
Rand
into functions and structures that called for aRand
. I think this is mitigated by the current math/rand docs that recommend seeding and point at crypto/rand for security-sensitive work. -
A few extra characters (e.g.
rand.Intn
->rand.GlobalRand.Intn
) for folks calling the global in Go 2+.
Personally I think the "simpler API" arguments are fairly strong. The "user convenience" argument is weaker, because calling rand.New(rand.NewSource(yourSeed()))
is not much more difficult than using rand.GlobalRand
after having previously called rand.GlobalRand.Seed(yourSeed())
. But I don't think the arguments against are very strong either, so on the whole I come out in favor of the global. I'm not a maintainer though, and I may be missing things.
I also wouldn't be surprised if this had been proposed before, but I have been unable to turn up references to it (either in this repo's issues or in the golang-dev@ logs). The current private globalRand
dates back to 3342574 (2009-10-15). The commit message has OCL
and CL
tags, which may be related to external review (like the modern Reviewed-on
), but if so, I'm not sure where that review is stored.