10 15
聊聊golang的rand

使用golang生成随机数的时候,官方提供了两种方式,分别是 math/randcrypo/rand ,那么它们两者之间究竟有什么 不同呢?如果通过它们来生成我们的随机数呢?下面我们一起来聊聊golang的随机数生成方式。

什么是随机数
很多软件和应用都需要随机数,从纸牌游戏中纸牌的分发到 SSL 安全协议中密钥的产生,到处都有随机数的身影。随机数至少具备两个条件: 数字序列在统计上是随机的 不能通过已知序列推算后面的序列 自从计算机诞生起,寻求用计算机产生高质量的随机数序列的研究就一直是研究者长期关注的课题。
一般情况下,使用计算机程序产生一个真正的随机数是很难的,因为程序的行为是可预测的,计算机利用设计好的算法结合用户提供的种子产生的随机数序列通常是“伪随机数”(pseudo-random number),伪随机数就是我们平时经常使用的“随机数”。伪随机数可以满足一般应用的需求,但是在对于安全要求比较高的环境和领域中存在明显的缺点:
例如:
1.伪随机数是周期性的,当它们足够多时,会重复数字序列
2.如果提供相同的算法和相同的种子值,将会得出完全一样的随机数序列
3.可以使用逆向工程,猜测算法与种子值,以便推算后面所有的随机数列
生成随机数是密码学中的一项基本任务,是生成加密密钥、加密算法和加密协议所必不可少的,随机数的质量对安全性至关重要

Go 的rand包:math/randcrypo/rand, 前者是一种伪随机数生成方式,后者是真正意义上的随机数生成方式。

math/rand

go源码包是这样描述的:

Package rand implements pseudo-random number generators.
Random numbers are generated by a Source. Top-level functions, such as Float64 and Int, use a default shared Source that produces a deterministic sequence of values each time a program is run. Use the Seed function to initialize the default Source if different behavior is required for each run.
The default Source is safe for concurrent use by multiple goroutines. For random numbers suitable for security-sensitive work, see the crypto/rand package.

math/rand比crypo/rand提供了更丰富的api:

  • 提供能以不同数字格式(float33,float64,int32,int64,…)返回的均匀分布的随机值的方法。

  • 根据非均匀(正态分布和指数分布)float64值分布返回的方法。

  • 能生成zipf分布值

  • 可生成置换切片的方法

math/rand 另外一个特点是它比 crypo/rand 快

crypto/rand

查看go的源码,我们发现math/rand里包含rng.go的实现,但我们在crypto/rand找不到,潜台词就是说,crypto/rand 没有实现rng的算法。 它完完全全依赖的是操作系统的安全加密方式的随机数算法方式。 crypto/rand 的实现要稍慢一

总的来说math/rand是最简单的随机数,例如你要随机一个1-100之间的数字, 而crypto/rand是更加复杂的,例如beego里面的sessionid,他有一个很大的特点是不可预测。所以如果你要实现一些涉及安全的 上下文,建议还是使用crypto/rand, 如果只是简单生成随机数,math/rand是首选。

第三方开源的rand库

除了使用官方的库,开发我们自己随机数功能外,我们还能使用一些第三方库,来根据我们的需要,实现一些随机数生成功能。

random
distuv
golang-petname
go-randomdata