go生成随机数

用习惯了python里面的random模块,随机数真的是顺手就来,这次用到了go,没想到生成的居然是伪随机数,首次生成虽然随机了,但是再次生成就一直是这个,这怎么搞,完全没随机啊,下面说一说踩过的坑!!!

1. 首先来说一下什么是随机数

随机数,是使用一个确定性的算法计算出来随机数序。在程序开发中经常需要产生随机数,如随机数验证码登陆、作为唯一身份标识数据等等。

2. go中生成随机数的有两个包,分别是“math/rand”和“crypto/rand”,

  • 前者实现了伪随机数生成器,
  • 后者实现了用于加解密的跟安全的随机数生成器,当然,性能也就降下来了,毕竟鱼与熊掌不可兼得

3. 随机数生成

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 -->还是这个结果,这叫啥子随机数,查看文档,继续试验

4. 初始化随机种子函数(下面为官方文档说明)

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方法是并发安全的.
所谓种子,通俗理解可以理解为一个抽奖的奖池,我们自定义一个奖池,从我们的奖池中进行随机抽奖,种子就是我们奖池中的数据

5. 使用种子生成

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)
}

6. Intn函数

func Intn(n int) int

生成 [0,n)区间的一个随机数(注意:不包括n)
更多详情查看math/rand官网

7. 生成指定位数的随机数(以生成8位为例)

package main
import (
   "fmt"
   "math/rand"func main() {
	s := fmt.Sprintf("%08v", rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(100000000))
	fmt.Println(s)
}

8. 真随机数

如果我们的应用对安全性要求比较高,需要使用真随机数的话,那么可以使用 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)
 }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章