Go1.22 新特性:新的 math/rand/v2 库,更快更规范了!

大家好,我是煎鱼。

Go 首个标准准库的 v2 版本,来自 math/rand/v2 库。将在 Go1.22 正式发布和对外生产可用。

本次由 Go 核心团队负责人 @Russ Cox 推动和发起。

变动原因

选择 math/rand 库做第一个 v2 标准库变动的原因如下:

  1. 标准库里的 math/rand 的老毛病和待提高的地方太多了。例如:过时的生成器、缓慢的算法(性能),以及与 crypto/rand.Read 的不幸冲突等问题。
  2. 计划推动标准库的 v2 版本升级。先用 math 试试水,积累经验。例如:解决工具生态的问题(gopls、goimports 等工具对 v2 包的支持)。后续再对风险更高的包(如:sync/v2 或 encoding/json/v2)进行新版本迭代。
  3. Go1 要求兼容性保障,没法直接对原库进行变更。math/rand 的问题也比较显著和明显。

变动清单

  • 删除 Rand.Read 和顶层的 Read。
  • 移除 Source.Seed、Rand.Seed 和顶层 Seed。(意味着像 Int 这样的顶层函数将总是随机播种)
  • 移除 Source64,现在 Source 提供了 Uint64 方法,原有的方法没有必要存在了。
  • 在 Float32 和 Float64 中使用更直接的实现。以 Float64 为例,它最初使用 float64(r.Int63()) / (1<<63)。但这有一个问题,就是偶尔会四舍五入到 1.0,而 Float64 一定不会。我们期望改成 float64(r.Int63n(1<<53)) / (1<<53),这就避免了四舍五入的问题。
  • 用 Rand.Shuffle 的方式实现 Rand.Perm。Shuffle 的效率更高一些,这样可以确保只有一个实现。
  • 将 Int31、Int31n、Int63、Int64n 更名为 Int32、Int32n、Int64、Int64n。这些名字是不必要的迂腐和混乱。
  • 添加 Uint32, Uint32n, Uint64, Uint64n, Uint, Uintn,将会是 Rand 上的顶级函数和方法。
  • 在 Intn, Uintn, Int32n, Uint32n, Int64n, Uint64n 中使用 Lemire 的算法。性能会有新的突破。
  • 添加一个新的 Source 实现,PCG-DXSM。包含:NewPCG 等相关 API 可以调用。
  • 删除 Mitchell & Reeds LFSR 生成器和 NewSource。

一些案例

Read、Seed 函数已被删除

在 math/rand 中存在 Read 函数,他在 v1 版本已经被弃用。

Seed 函数也是:

以上两个方法在 v2 版本中已被正式剔除。

Read,如有类似使用的诉求,会建议使用 crypto/rand 的 Read 来代替:

go 复制代码
import (
	"crypto/rand"
	"fmt"
)

func main() {
	b := make([]byte, 3)
	_, err := rand.Read(b)
	if err != nil {
		panic(err)
	}
	fmt.Printf("煎鱼: %v\n", b)
}

输出结果:

ini 复制代码
煎鱼: [49 71 122]

Seed,建议调用 New(NewSource(seed)) 来重新初始化随机数生成器。

变更部分内部算法实现

函数 N、IntN、UintN 使用了新的实现算法,有兴趣的同学可以另外抽时间详细看:《A fast alternative to the modulo reduction》。

新增和改变各 IntN 等函数

以前的函数名有混淆且命名不够规范的问题。

函数 Intn、Int31、Int31n、Int63、Int64n 已分别重命名为 IntN、Int32、Int32N、Int64、Int64N。 新增了函数 Uint32、Uint32N、Uint64、Uint64N、Uint、UintN 来生成随机无符号整数。也作为同名函数添加到结构体 Rand 中。

新增 N 函数

添加了一个函数 N,用于生成任意整数类型的随机数。该函数是基于泛型实现的,以下整数类型是他的类型参数:

go 复制代码
type intType interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 |
		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blo... 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

总结

今天给大家再次分享和更进一步描述了新的 math/rand/v2 库,本次主要变更点在于性能优化(算法重写)、规范和统一、新的随机生成器和实现补充等。

完整阐述的话内容物是比较多的,本次仅挑了一些我觉得使用端上有必要了解的。如果有想进一步了解的同学可以细看:math/rand/v2

相关推荐
研究司马懿17 小时前
【云原生】Gateway API高级功能
云原生·go·gateway·k8s·gateway api
梦想很大很大1 天前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
lekami_兰2 天前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
却尘2 天前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤2 天前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt112 天前
AI DDD重构实践
go
Grassto4 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto5 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室6 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题6 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo