@@ -16,17 +16,17 @@ import (
16
16
// UUID represents a UUID.
17
17
type UUID [16 ]byte
18
18
19
- // random is a package-global pseudo-random number generator.
20
- var random = randutil .NewLockedRand (rand .NewSource (randutil .CryptoSeed ()))
19
+ // A source is a UUID generator that reads random values from a randutil.LockedRand.
20
+ // It is safe to use from multiple goroutines.
21
+ type source struct {
22
+ random * randutil.LockedRand
23
+ }
21
24
22
- // New returns a random UUIDv4. It uses a "math/rand" pseudo-random number generator seeded with a
23
- // cryptographically-secure random number at package initialization.
24
- //
25
- // New should not be used to generate cryptographically-secure random UUIDs.
26
- func New () (UUID , error ) {
25
+ // new returns a random UUIDv4 with bytes read from the source's random number generator.
26
+ func (s * source ) new () (UUID , error ) {
27
27
var uuid [16 ]byte
28
28
29
- _ , err := io .ReadFull (random , uuid [:])
29
+ _ , err := io .ReadFull (s . random , uuid [:])
30
30
if err != nil {
31
31
return [16 ]byte {}, err
32
32
}
@@ -36,6 +36,26 @@ func New() (UUID, error) {
36
36
return uuid , nil
37
37
}
38
38
39
+ // newGlobalSource returns a source that uses a "math/rand" pseudo-random number generator seeded
40
+ // with a cryptographically-secure random number. It is intended to be used to initialize the
41
+ // package-global UUID generator.
42
+ func newGlobalSource () * source {
43
+ return & source {
44
+ random : randutil .NewLockedRand (rand .NewSource (randutil .CryptoSeed ())),
45
+ }
46
+ }
47
+
48
+ // globalSource is a package-global pseudo-random UUID generator.
49
+ var globalSource = newGlobalSource ()
50
+
51
+ // New returns a random UUIDv4. It uses a "math/rand" pseudo-random number generator seeded with a
52
+ // cryptographically-secure random number at package initialization.
53
+ //
54
+ // New should not be used to generate cryptographically-secure random UUIDs.
55
+ func New () (UUID , error ) {
56
+ return globalSource .new ()
57
+ }
58
+
39
59
// Equal returns true if two UUIDs are equal.
40
60
func Equal (a , b UUID ) bool {
41
61
return a == b
0 commit comments