golang随机整数和随机整数切片
1.随机整数
// GetRandomInt 随机获得一个在一定范围内的整数,范围[mi,mx) func GetRandomInt(mi int, mx int) (int, error) { if mi >= mx { return 0, errors.New("输入的整数范围有误") } // 这里实时生成随机种子,而不用全局随机种子 source := rand.NewSource(time.Now().UnixNano()) rng := rand.New(source) randomInt := rng.Intn(mx-mi) + mi return randomInt, nil }
2.随机整数切片
// GetUniqueRandomInts 随机获得在一定范围内的多个且唯一的整数,范围[mi,mx),结果是整数切片 func GetUniqueRandomInts(mi, mx, count int) ([]int, error) { if mi >= mx { return nil, errors.New("输入的整数范围有误") } if count > mx-mi { return nil, errors.New("要求的数量超限") } // 初始化包含指定范围所有整数的切片 numbers := make([]int, mx-mi) for i := range numbers { numbers[i] = mi + i } // 打乱切片顺序 source := rand.NewSource(time.Now().UnixNano()) rng := rand.New(source) rng.Shuffle(len(numbers), func(i, j int) { numbers[i], numbers[j] = numbers[j], numbers[i] }) // 截取所需数量的元素 return numbers[:count], nil }
3.拓展
- 两个函数都使用了时间纳秒作随机种子,适用大部分场景,需要更高的安全性可以采用"seed, _ := rand.Int(rand.Reader, big.NewInt(1<<63-1))"生成更安全的种子.
4.对于随机整数切片的生成, 大模型给出的适用性更强的方案
func GetUniqueRandomInts(mi, mx, count int) ([]int, error) { // 参数校验 if mi >= mx { return nil, fmt.Errorf("无效范围 [%d, %d)", mi, mx) } if count > mx-mi { return nil, fmt.Errorf("请求数量 %d 超过范围大小 %d", count, mx-mi) } // 小范围直接全量洗牌 if mx-mi <= 1000 || count > (mx-mi)/2 { numbers := make([]int, mx-mi) for i := range numbers { numbers[i] = mi + i } seed, _ := rand.Int(rand.Reader, big.NewInt(1<<63-1)) rng := rand.New(rand.NewSource(seed.Int64())) rng.Shuffle(len(numbers), func(i, j int) { numbers[i], numbers[j] = numbers[j], numbers[i] }) return numbers[:count], nil } // 大范围使用蓄水池抽样 result := make([]int, count) for i := 0; i < count; i++ { result[i] = mi + i } seed, _ := rand.Int(rand.Reader, big.NewInt(1<<63-1)) rng := rand.New(rand.NewSource(seed.Int64())) for i := count; i < mx-mi; i++ { if j := rng.Intn(i + 1); j < count { result[j] = mi + i } } return result, nil }