golang生成随机数
人为什么害怕独处呢?因为人在独处的时候,总是会听到心里深处的声音,这个心灵深处的声音会不断逼问你,你这一生到底想干嘛?
Pseudorandom numbers
The math/rand
package provided by the Go Standard Library gives us pseudo-random number generators (PRNG), also called deterministic random bit generators.
As with all pseudo number generators, any number generated through math/rand
is not really random by default, as being deterministic it will always print the same value each time.
As an example, try running this code which introduces rand.Intn(n)
, which returns a random number between 0
and n - 1
.
1 | package main |
You’ll always see the same sequence every time you run the program. The random number changes inside the program, but every time you run it, you’ll get the same output:
1 | 11 |
This is because by default the seed is always the same, the number 1. To actually get a random number, you need to provide a unique seed for your program. You really want to not forget seeding, and instead properly seed our pseudonumber generator. How?
Use rand.Seed()
before calling any math/rand
method, passing an int64
value. You just need to seed once in your program, not every time you need a random number. The most used seed is the current time, converted to int64
by UnixNano with rand.Seed(time.Now().UnixNano())
:
1 | package main |
Remember that due to its sandboxing, the Go Playground always begins with the same time, so this code won’t work as expected. Try it on a real environment, and the numbers that previosly didn’t change, they will now print differently each time you run the program.
Some common examples are listed below for ease of reuse:
Generate a random integer
1 | package main |
Generate a random string
1 | package main |
Will return 10 chars in uppercase format. Change
1 | bytes[i] = byte(randomInt(65, 90)) |
to
1 | bytes[i] = byte(randomInt(97, 122)) |
for just lowercase.
If you instead want to have a pool of specific chars to pick from, use
1 | package main |
Change len(pool) to utf8.RuneCountInString(pool) if you use non-ascii strings, as len() counts the bytes, but not all chars take just one byte in Unicode - see https://stackoverflow.com/questions/12668681/how-to-get-the-number-of-characters-in-a-string.
Generate a random array of integers
1 | package main |
Crypto-level random numbers
Go also provides a Cryptographically secure pseudorandom number generator (CSPRNG) in the standard library package crypto.rand
So you might question, why should I even use the pseudo-number random generator library provided by math/rand
instead? Well, it depends on the use case. math/rand
is much faster for applications that don’t need crypto-level or security-related random data generation. crypto.rand is suited for secure and crypto-ready usage, but it’s slower.
What it should be used for? For example, generating passwords, CSRF tokens, session keys, or anything remotely related to security.
It does not rely on the current time, like we did in the previous examples in math/rand, but instead it uses the operating system CSPRNG APIs: the CryptGenRandom API on Windows, and /dev/urandom/
on all the others (Linux, OSX, *nix
)
You get 256 random bytes directly with
1 | package main |
I’m taking a code sample from Matt Silverlock: you can make it more general and create a random bytes generation function
1 | // GenerateRandomBytes returns securely generated random bytes. |
and using this, a random string generation function,
1 | // GenerateRandomString returns a URL-safe, base64 encoded |