Go 语言生成随机数的两种方式:math/rand 与 crypto/rand
在Go开发中,根据业务场景对安全性的不同要求,通常采用两种随机数生成方案:math/rand 生成的伪随机数和 crypto/rand 生成的真随机数。本文详解两者的区别、使用方法及自定义字符串生成实现。
Go 语言随机数核心区别
Go 语言标准库提供了两套独立的随机数机制,其根本区别在于来源与适用场景:
math/rand:伪随机数生成器。基于算法确定性地生成数字序列,性能高但可预测。适用于游戏逻辑、数据模拟等非安全敏感场景。crypto/rand:真随机数生成器。直接从操作系统获取熵源(如硬件中断),符合 NIST 标准,具有不可预测性但性能较低。适用于密钥生成、令牌验证等安全敏感场景。
第1步:使用 math/rand 生成伪随机数
由于伪随机数算法依赖于初始状态(Seed),若不设置种子,每次程序启动生成的“随机”序列将完全一致。为确保每次运行结果不同,需使用时间戳作为种子。
1.1 基础随机整数生成
通过 rand.Seed 初始化随机种子,随后调用 rand.Intn 获取指定范围内的整数。注意:该示例使用了较早期的 API 调用方式。
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// 1. 设置随机数种子,基于当前时间纳秒
rand.Seed(time.Now().UnixNano())
// 2. 生成 [0, 100) 之间的随机整数
fmt.Println(rand.Intn(100))
}
1.2 自定义随机字符串生成
在实际开发中,常需生成由特定字符集组成的随机字符串(如验证码)。以下代码演示了如何混合数字、大小写字母生成随机串。
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// 生成6位纯数字随机码
fmt.Println(randomString(6, 0))
}
// size: 随机字符串长度
// kind: 0=纯数字, 1=小写字母, 2=大写字母, 3=混合
func randomString(size int, kind int) string {
ikind := kind
// 定义字符集范围:[数量, ASCII起始值]
kinds := [][]int{
{10, 48}, // 0-9 (ASCII 48)
{26, 97}, // a-z (ASCII 97)
{26, 65}, // A-Z (ASCII 65)
}
rsbytes := make([]byte, size)
// 设置随机种子
rand.Seed(time.Now().UnixNano())
for i := 0; i < size; i++ {
isAll := kind > 2 || kind < 0
if isAll {
// 混合模式:每轮随机选择一种字符类型
ikind = rand.Intn(3)
}
scope := kinds[ikind][0]
base := kinds[ikind][1]
// 计算字符并转换
rsbytes[i] = uint8(base + rand.Intn(scope))
}
return string(rsbytes)
}
第2步:使用 crypto/rand 生成真随机数
当应用场景涉及安全性时,应使用 crypto/rand。该包从系统熵池读取数据,无法被预测,但 I/O 开销较大,不适合高频调用场景。
2.1 基本真随机数获取
通过 binary.Read 将 crypto/rand.Reader 的字节流转换为整数类型。
package main
import (
"crypto/rand"
"encoding/binary"
"fmt"
)
func main() {
var n int32
// 从 crypto/rand 读取 4 字节数据填充到 n
error := binary.Read(rand.Reader, binary.LittleEndian, &n)
if error != nil {
fmt.Printf("Error reading from rand: %v\n", error)
return
}
fmt.Println(n)
}
注意事项与最佳实践
- 版本差异提醒:在 Go 1.20 及以上版本中,
math/rand的默认源已改为全局默认值,不再强制要求手动调用rand.Seed,因为全局源已在程序启动时自动初始化。但在旧版本或需要显式控制时,上述rand.Seed方法依然有效且必要。 - 性能权衡:除非业务明确要求不可预测性,否则优先使用
math/rand,因其速度比crypto/rand快数十倍。 - 错误处理:在使用
crypto/rand进行二进制读取时,务必检查返回的错误,确保数据正确解析。
以上就是 Go 语言随机数生成方式的详细内容,更多关于 Golang 数学库与加密模块的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













