用习惯了python里面的random模块,随机数真的是顺手就来,这次用到了go,没想到生成的居然是伪随机数,首次生成虽然随机了,但是再次生成就一直是这个,这怎么搞,完全没随机啊,下面说一说踩过的坑!!!
随机数,是使用一个确定性的算法计算出来随机数序。在程序开发中经常需要产生随机数,如随机数验证码登陆、作为唯一身份标识数据等等。
func main() {
for i:=0; i<10; i++ {
fmt.Print(rand.Intn(10), " ")
}
}
结果: 1 7 7 9 1 8 5 0 6 0 --> 生成的是
再来一次: 1 7 7 9 1 8 5 0 6 0 -->还是这个结果,这叫啥子随机数,查看文档,继续试验
func Seed(seed int64)
Seed uses the provided seed value to initialize the default Source to a deterministic state. If Seed is not called, the generator behaves as if seeded by Seed(1). Seed values that have the same remainder when divided by 2^31-1 generate the same pseudo-random sequence. Seed, unlike the Rand.Seed method, is safe for concurrent use.
我认为的意思就是系统每次都会先用Seed函数初始化系统资源,如果用户不提供seed参数,则默认用seed=1来初始化,这就是为什么每次都输出一样的值的原因,而且,Seed方法是并发安全的.
所谓种子,通俗理解可以理解为一个抽奖的奖池,我们自定义一个奖池,从我们的奖池中进行随机抽奖,种子就是我们奖池中的数据
func main() {
// 我们一般使用系统时间的不确定性来进行初始化
rand.Seed(time.Now().Unix())
for i:=0; i<10; i++ {
fmt.Print(rand.Intn(10), " ")
}
}
或者我们可以使用rand.NewSource()
func checkSumBuilder() (string, string, string){
r := rand.New(rand.NewSource(time.Now().UnixNano()))
num := r.Intn(128)
}
func Intn(n int) int
生成 [0,n)区间的一个随机数(注意:不包括n)
更多详情查看math/rand官网
package main
import (
"fmt"
"math/rand"
)
func main() {
s := fmt.Sprintf("%08v", rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(100000000))
fmt.Println(s)
}
如果我们的应用对安全性要求比较高,需要使用真随机数的话,那么可以使用 crypto/rand 包中的方法,这样生成的每次都是不同的随机数.
package main
import (
"crypto/rand"
"fmt"
"math/big"
)
func main() {
// 生成 10 个 [0, 128) 范围的真随机数。
for i := 0; i < 10; i++ {
result, _ := rand.Int(rand.Reader, big.NewInt(128))
fmt.Println(result)
}
}