从Go 1.13迁移至1.20.1时,如何改写rand.Seed(1)?
问题解决:Go 1.20+ 替换 rand.Seed(1) 的正确方式
在Go 1.13到1.20.1的迁移中,直接将rand.Seed(1)替换为rand.NewSource(1)会测试失败,核心原因是:rand.NewSource(1)仅创建了固定种子的随机源,但并未绑定到实际使用的随机生成器,全局rand包的函数依然使用默认种子生成随机序列,导致测试数据和预期不一致。
正确改写方案
需要创建一个本地的rand.Rand实例,基于固定种子的源生成随机数,确保所有随机调用都使用这个实例,而非全局rand函数:
修改bench_test.go中的makeData和makeWord函数如下:
func makeData() { file, err := os.Create("testdata/data.txt") if err != nil { panic(err) } defer file.Close() // 创建固定种子的随机源和对应的Rand实例 rng := rand.New(rand.NewSource(1)) for i := 0; i < 10000; i++ { // 使用本地rng实例生成随机数 data := makeWord(rng, rng.Intn(10)+1) file.Write(data) } } // 修改makeWord函数,接收Rand实例作为参数 func makeWord(rng *rand.Rand, l int) []byte { out := make([]byte, l+1) for i := 0; i < l; i++ { // 使用本地rng实例生成随机数 out[i] = 'a' + byte(rng.Intn(26)) } out[l] = '\n' return out }
改写说明
- 创建本地Rand实例:
rand.New(rand.NewSource(1))生成一个基于固定种子的独立随机生成器,既避免全局rand的并发问题,也保证每次运行的随机序列完全一致。 - 传递Rand实例:将
makeWord函数修改为接收*rand.Rand参数,确保所有随机数生成都使用这个固定实例,和原rand.Seed(1)的全局随机序列完全匹配。 - 保持测试一致性:修改后生成的
testdata/data.txt大小仍为65204字节,TestFileLen测试可以顺利通过。
直接替换失败的原因
- Go 1.20中
rand.Seed已被废弃,它的作用是设置全局rand的默认源种子; - 仅调用
rand.NewSource(1)不会改变全局rand的源,全局rand依然使用默认种子生成随机数,导致测试数据和预期不符,测试失败。
内容的提问来源于stack exchange,提问作者Đỗ Như Vỹ
相关产品推荐
相关产品推荐

