Go生成随机数需用time.Now().UnixNano()设种子,Go 1.20+应使用rand.New(rand.NewSource())避免全局竞争;安全场景须用crypto/rand,非安全场景用math/rand即可。

Go 生成随机数必须先 seed,否则每次运行结果一样
Go 的 math/rand 默认使用固定种子(0),所以不显式设置的话,rand.Intn(10) 每次跑都是同一串数字。这不是 bug,是设计——方便测试;但生产环境必须自己 seed。
正确做法是用当前时间纳秒做种子:
rand.Seed(time.Now().UnixNano())
注意:rand.Seed 在 Go 1.20+ 已被标记为 deprecated,推荐改用 rand.New(rand.NewSource(...)) 实例化独立的随机数生成器,避免全局状态干扰并发:
- 多个 goroutine 同时调
rand.Intn可能竞争,用局部*rand.Rand更安全 -
rand.NewSource(time.Now().UnixNano())返回的是rand.Source,要包一层rand.New()才能调方法 - 如果只是临时用,直接
rand.New(rand.NewSource(time.Now().UnixNano())).Intn(10)
生成指定长度的随机字符串(字母+数字)
常见需求是生成 token、文件名或 session ID,不能只靠 rand.Intn 拼字符,得映射到合法字符集。核心是定义字符池 + 循环取索引。
示例:生成 8 位大小写字母+数字的字符串:
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
src := rand.New(rand.NewSource(time.Now().UnixNano()))
b := make([]byte, 8)
for i := range b {
b[i] = letters[src.Intn(len(letters))]
}
s := string(b)
注意点:
- 别用
strings.Builder或+=拼接 byte,小长度下切片预分配更快 - 如果要求“必须含大小写和数字”,上面方案不保证——它纯随机,可能全大写。需要强制校验重试,或分段生成再 shuffle
- 密码学安全场景(如密钥)不能用
math/rand,得换crypto/rand+Read
生成 4–6 位数字验证码(带可选干扰线/噪点)
后端生成验证码通常只要字符串,前端渲染或发短信用;但有些老系统仍需服务端画图返回 PNG。这里聚焦「字符串生成」本身。
最简数字验证码(如短信验证码)只需:
n := 4 // 或 6
src := rand.New(rand.NewSource(time.Now().UnixNano()))
digits := make([]byte, n)
for i := range digits {
digits[i] = byte('0' + src.Intn(10))
}
code := string(digits)
常见陷阱:
- 别写
src.Intn(9) + 1想避开 0——这样就少了 0,实际范围变成 1–9,不是 0–9 - 如果存 Redis 做校验,注意过期时间设够(比如 5 分钟),且 key 命名带用户标识,防止撞库
- 图形验证码若用
image/draw生成,记得设置字体(默认无中文字体)、抗锯齿,否则中文乱码或模糊不清
crypto/rand 替代 math/rand 的时机和代价
当随机值用于生成 API token、JWT 密钥、加密盐值(salt)等安全敏感场景时,math/rand 不够用——它可预测,crypto/rand 读取操作系统熵池(Linux 的 /dev/urandom),不可预测。
用法差异明显:
-
crypto/rand没有Intn,只有Read([]byte),得自己把字节转整数 - 生成 6 位数字验证码用
crypto/rand反而麻烦:要循环读字节、模 10、跳过溢出,性能略低 - 典型安全用途:生成 AES key →
key := make([]byte, 32); rand.Read(key) - 非安全用途(如 mock 数据、游戏骰子)坚持用
math/rand,快且足够
真正容易被忽略的是:很多人以为“用了 crypto/rand 就绝对安全”,其实如果 seed 来源没隔离(比如多个服务共用同一熵源且未 reseed),或 key 没正确擦除内存,照样出问题。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











