Go中math/rand默认用固定种子1,故每次运行生成相同序列;需用time.Now().UnixNano()设种子,Go 1.20+推荐rand.New(rand.NewSource())避免全局污染,且goroutine中应使用独立实例;rand.Intn(n)生成[0,n)随机数,n为0会panic。

Go 中 math/rand 为什么总生成相同数字?
默认不设置种子时,rand.Intn() 每次运行都返回完全相同的序列。这不是 bug,而是设计行为:未调用 rand.Seed() 时,底层使用固定种子 1。
- 必须在程序启动早期(如
main()开头)调用rand.Seed(time.Now().UnixNano()) - Go 1.20+ 推荐改用
rand.New(rand.NewSource(time.Now().UnixNano()))实例,避免全局状态污染 - 若在 goroutine 中高频调用全局
rand.*函数,可能因竞态导致重复或 panic —— 此时务必用独立的*rand.Rand实例
如何安全生成 [0, n) 区间的随机整数?
rand.Intn(n) 是最常用方法,但要注意它只接受非负整数,且 n == 0 会 panic。
- 生成 1~6 的骰子点数:
rand.Intn(6) + 1 - 生成指定范围 [min, max] 的整数:
min + rand.Intn(max-min+1)(需确保max >= min) - 若
n来自用户输入,务必先校验:if n
生成随机字符串或字节切片的常见写法
标准库不直接提供随机字符串生成,需组合 rand.Intn() 和字符集。
网趣购物系统静态版支持网站一键静态生成,采用动态进度条模式生成静态,生成过程更加清晰明确,商品管理上增加淘宝数据包导入功能,与淘宝数据同步更新!采用领先的AJAX+XML相融技术,速度更快更高效!系统进行了大量的实用性更新,如优化核心算法、增加商品图片批量上传、谷歌地图浏览插入等,静态版独特的生成算法技术使静态生成过程可随意掌控,从而可以大大减轻服务器的负担,结合多种强大的SEO优化方式于一体,使
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
func RandString(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
- 不要用
rand.Read()直接填充字符串 —— 它写入的是字节,不是 UTF-8 安全的 rune 序列 - 若需密码级随机性(如 token),必须用
crypto/rand替代math/rand,后者是伪随机,不适用于安全场景 - 字符集应显式定义,避免依赖
unicode包动态判断 —— 性能差且逻辑易出错
Go 1.20+ 推荐的无竞态初始化方式
全局 rand.* 函数共享一个锁,高并发下成瓶颈;且无法单独控制不同模块的随机行为。
立即学习“go语言免费学习笔记(深入)”;
var globalRand = rand.New(rand.NewSource(time.Now().UnixNano())) // 在需要的地方直接用 n := globalRand.Intn(100) // 或为特定逻辑创建隔离实例 taskRand := rand.New(rand.NewSource(time.Now().UnixNano()))
- 每个 goroutine 或业务逻辑块应持有自己的
*rand.Rand实例,而非反复调用全局函数 - 若需可重现的随机序列(如测试、游戏存档),传入固定
int64种子,例如rand.NewSource(12345) - 注意
time.Now().UnixNano()在容器或虚拟机中可能不够随机 —— 生产环境关键服务建议结合/dev/urandom或外部熵源
math/rand,以及并发下没隔离实例导致结果可预测或性能陡降**。









