Go语言标准库中的math/rand包提供了生成伪随机数的功能,适用于大多数不需要密码学级别随机性的场景,正确使用该包需要了解其导入方式、生成逻辑和注意事项。

math/rand包的导入方式
使用math/rand包首先需要进行导入,标准导入方式如下:
// 导入math/rand包,用于生成随机数 import "math/rand"
如果还需要使用时间相关的功能来初始化随机数种子,可以同时导入time包:
import (
"math/rand"
"time"
)
基础随机数生成方法
生成随机整数
math/rand包提供了多个生成随机整数的方法,最常用的是rand.Int()和rand.Intn(n):
rand.Int():生成一个非负的随机整数,范围在0到最大整数值之间rand.Intn(n):生成一个0到n-1之间的随机整数,n必须为正整数
示例代码如下:
package main
import (
"fmt"
"math/rand"
)
func main() {
// 生成随机整数
num1 := rand.Int()
fmt.Printf("随机整数: %dn", num1)
// 生成0到9之间的随机整数
num2 := rand.Intn(10)
fmt.Printf("0到9之间的随机整数: %dn", num2)
}
生成随机浮点数
如果需要生成随机浮点数,可以使用rand.Float64()方法,该方法会返回0.0到1.0之间的随机浮点数:
package main
import (
"fmt"
"math/rand"
)
func main() {
// 生成0到1之间的随机浮点数
floatNum := rand.Float64()
fmt.Printf("随机浮点数: %fn", floatNum)
// 生成1到10之间的随机浮点数
customFloat := 1 + rand.Float64()*9
fmt.Printf("1到10之间的随机浮点数: %fn", customFloat)
}
随机数种子的重要性
math/rand包生成的是伪随机数,默认情况下如果没有设置种子,每次程序运行生成的随机数序列都是相同的。为了让每次运行生成的随机数不同,需要设置随机种子,通常使用当前时间戳作为种子:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// 使用当前时间戳初始化随机种子
rand.Seed(time.Now().UnixNano())
// 生成随机数
for i := 0; i < 5; i++ {
fmt.Printf("第%d个随机数: %dn", i+1, rand.Intn(100))
}
}
需要注意的是,Go 1.20版本之后,rand.Seed方法已经被废弃,官方推荐使用rand.New(rand.NewSource(seed))来创建新的随机数生成器:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// 创建新的随机数生成器并设置种子
r := rand.New(rand.NewSource(time.Now().UnixNano()))
// 使用新的生成器生成随机数
for i := 0; i < 5; i++ {
fmt.Printf("第%d个随机数: %dn", i+1, r.Intn(100))
}
}
常见注意事项
- math/rand包生成的伪随机数不适合用于密码学场景,密码学场景请使用crypto/rand包
- 不要在每次生成随机数时都初始化种子,否则如果时间间隔太短,可能会生成相同的随机数
- 如果需要并发安全的随机数生成,要么加锁使用全局的rand实例,要么给每个协程创建独立的随机数生成器
常用方法汇总
以下是math/rand包常用方法的说明:
| 方法名 | 功能说明 |
|---|---|
| rand.Int() | 生成非负随机整数 |
| rand.Intn(n) | 生成0到n-1之间的随机整数 |
| rand.Float64() | 生成0.0到1.0之间的随机浮点数 |
| rand.Perm(n) | 生成长度为n的随机排列切片,元素为0到n-1 |
| rand.Shuffle(n, swap func(i, j int)) | 随机打乱切片顺序 |
通过以上内容,就可以正确导入和使用math/rand包生成符合需求的随机数了。