Go1.23 于北京时间 2024 年 8 月 14 日凌晨 1:03 正式发布。此次更新的主要变化集中在工具链、运行时和库的实现上。让我们一起来看看 Go 1.23 带来了哪些新变化吧!
1.迭代器支持:
Go 1.23 正式将 range 语句支持迭代器函数纳入语言规范。现在,range 子句可以接受三种类型的迭代器函数:func(func() bool)、func(func(K) bool) 和 func(func(K, V) bool)。
这些迭代器函数可以在用户定义的容器类型上实现遍历,从而避免直接暴露内部数据结构。
示例代码:
package main
import "fmt"
func main() {
s := []string{"程序员", "陈明勇"}
for i, v := range Backward(s) {
fmt.Println(i, v)
}
}
// Backward 函数实现倒序迭代
func Backward[E any](s []E) func(yield func(int, E) bool) {
return func(yield func(int, E) bool) {
for i := len(s) - 1; i >= 0; i-- {
if !yield(i, s[i]) {
return
}
}
}
}
2.泛型类型别名的预览支持:
Go 1.23 引入了泛型类型别名的预览支持。通过在构建工具链时设置 GOEXPERIMENT=aliastypeparams,可以在包内启用此功能(目前尚不支持跨包边界使用泛型类型别名)。
示例代码(假设已设置 GOEXPERIMENT=aliastypeparams):
package main
import "fmt"
type MyInt = int
func main() {
var a MyInt = 42
fmt.Println(a) // 输出: 42
}
3.工具链的改进:
Go telemetry 遥测系统:允许 Go 的工具链(编译器、调试器等工具)收集使用和故障统计数据,以改进和优化工具链。
Go 命令:新增了一些便利的功能,如 go env -changed 可以更容易地查看哪些设置的有效值与默认值不同,go mod tidy -diff 可以在不修改 go.mod 和 go.sum 文件的情况下查看需要进行的更改。
Go vet 子命令:现在能够检测代码中使用的某些特性或函数是否对于目标 Go 版本来说太新了。
4.标准库的改进:
优化了 time.Timer 与 time.Ticker 两个定时器的实现。
新增了三个包:iter、structs 和 unique。
iter:提供了与序列上的迭代器相关的基本定义和操作。
structs:定义了标记类型,用于修改结构体的属性。
unique:提供了规范化(“interning”)可比较值的工具。
支持在 go.mod 和 go.work 文件中使用新的 godebug 指令,以独立控制默认的 GODEBUG 和 go.mod 的 go 指令。
5.其他改进和变更:
为 OpenBSD 系统上的 64 位 RISC-V 架构提供了实验性支持。
包含了针对 Linux、macOS、ARM64、RISC-V 和 WASI 等系统的若干小改动。
在使用配置文件引导优化(PGO)技术的构建过程中,构建时间得到了缩短,且在 386 和 amd64 架构上运行性能也得到了提升。
go 指令的变更:
限制了 //go:linkname 指令的使用,以防止对标准库内容的滥用。
禁止对标准库的 “pull-only” //go:linkname 指令,但允许 “handshake” 模式。
添加了新的 ldflags:-checklinkname=1 选项来开启对 //go:linkname 的限制。
这些新特性和改进使得 Golang 1.23 版本在语言功能、工具链效率和标准库支持方面都有所提升,为开发者提供了更加强大和灵活的工具集。
更多变化查看 release note:https://go.dev/doc/go1.23
大家可以通过访问下载页面 https://go.dev/dl/ 获取 Go 1.23。
对于已安装 Go 1.22 或 Go 1.21 的用户,可以使用 go get toolchain@go1.23.0 来下载和使用新的工具链。
Go1.22 美国时间2023年12月20日,Go官方宣布Go 1.22rc1发布,开启了为期2个多月的、常规的公测之旅,Go 1.22于2024.2月份正式发布!
长期存在的 "for "循环在迭代之间意外共享循环变量的问题现已得到解决。
从 Go 1.22 开始,以下代码将按一定顺序打印 “a”、"b "和 “c”:
func main() {
done := make(chan bool)
values := []string{"a", "b", "c"}
for _, v := range values {
go func() {
fmt.Println(v)
done <- true
}()
}
// wait for all goroutines to complete before exiting
for _ = range values {
<-done
}
}
有关这一变更以及有助于防止代码意外中断的工具的更多信息,请参阅之前的《Fixing For Loops in Go 1.22[2]》。
第二个语言变化是支持整数范围:
package main
import "fmt"
func main() {
for i := range 10 {
fmt.Println(10 - i)
}
fmt.Println("go1.22 has lift-off!")
}
性能提高
Go 运行时中的内存优化可将 CPU 性能提高 1-3%,同时还可将大多数 Go 程序的内存开销减少约 1%。
在 Go 1.21 中,我们为 Go 编译器提供了配置文件引导优化 (PGO),而且这一功能还在不断改进。
Go 1.22 中新增的优化之一是改进了虚拟化,允许静态调度更多的接口方法调用。启用 PGO 后,大多数程序的性能将提高 2% 至 14%。
标准库变动
新的 math/rand/v2 软件包提供了更简洁、更一致的应用程序接口,并使用了质量更高、速度更快的伪随机生成算法。
net/http.ServeMux 使用的模式现在可接受方法和通配符。
例如:路由器接受 GET /task/{id}/ 这样的模式,该模式只匹配 GET 请求,并在一个可通过 Request 值访问的映射中捕获 {id} 段的值。
database/sql 包中新增了 Null[T] 类型,为扫描可为空的列提供了一种方法。
在 slices 包中添加了 Concat 函数,用于连接任意类型的多个片段。
运行时
-
垃圾收集元数据优化
Go 1.22 通过将垃圾收集元数据保持更接近每个堆对象来优化垃圾收集元数据。这提高了大多数程序的 CPU 性能 1–3%,并减少了内存开销。但是,它可能会影响依赖于特定内存对齐的程序,需要进行调整。 -
Windows/AMD64 增强
在 windows/amd64 端口上,程序现在可以使用 SetUnhandledExceptionFilter Win32 函数来捕获 Go 运行时未处理的异常,增强了调试功能。
核心库
-
Math/Rand 版本 2
Go 1.22 引入了标准库中的第一个“v2”包:math/rand/v2。此版本带来了改进,包括一个新的全局生成器和更快的算法。 -
增强的 HTTP 路由模式
net/http 标准库中的 HTTP 路由模式变得更加表达,支持方法、通配符,并改进了重叠模式的处理。
对库的次要更改
核心库经历了与 Go 1 兼容性承诺一致的各种次要更改和更新。此外,整体上进行了性能改进。
Go1.21.0 是2023年8月8日发布的Go语言的最新版本,它带来了一些语言和工具的变化。
• min和max内置函数:Go1.21.0增加了两个新的内置函数min和max,用来对任意可比较的有序类型进行最小值或最大值的操作。min和max函数可以接受一个或多个参数,并返回其中的最小值或最大值。如果参数是浮点数并且包含NaN,min和max函数会返回NaN。
• clear预定义函数:Go1.21.0增加了一个clear预定义函数用来做切片和map的clear操作。对于切片,clear函数会将所有元素设置为零值,但保持切片的长度和容量不变。对于map,clear函数会删除所有键值对,得到一个空map。clear函数的使用示例在[这里]展示。
• 改变panic(nil)语义:Go1.21.0改变了panic(nil)的语义,使得recover函数在捕获到panic(nil)时不再返回nil,而是返回一个特定的错误类型PanicNilError。这样可以避免开发者误以为没有发生panic,而继续执行正常逻辑。
• 新增标准库:slices、maps、slog 等 :这几个库正式进入标准库了。
Go 1.20 Release Notes - The Go Programming Language
特性:
• 支持将slice直接转为数组
• Comparable类型可比较
• unsafe包添加Slice,SliceData,String,StringData 4个函数
• 可移植性:Go 1.20将会成为支持macOS 10.13 High Sierra和10.14 Mojave的最后一个版本。
• Go 1.20增加了对于RISC-V架构在FreeBSD操作系统的实验性支持
• PGO引入
• 标准库加
○ 新增了几个 时间转换格式常量
○ 新包 crypto/ecdh 支持通过 NIST 曲线和 Curve25519 椭圆曲线 Diffie-Hellman 密钥交换
○ 新类型 http.ResponseController 访问 http.ResponseWriter 接口未处理的扩展请求
○ httputil.ReverseProxy 包含一个新的 Rewrite 钩子函数,取代了之前的 Director 钩子
○ 新方法 context.WithCancelCause 提供了一种方法来取消具有给定错误的上下文
○ os/exec.Cmd 结构体中的新字段 Cancel 和 WaitDelay, 指定 Cmd 在其关联的 Context 被取消或其进程退出时的回调
• 工具链
○ cover 工具可以收集整个程序的覆盖率,不仅仅是单元测试
○ go build、go install 和其他与构建相关的命令可以接收一个 -pgo 标志,启用配置文件引导优化,以及一个 -cover 标志,用于整个程序覆盖率分析
○ go test -json 的实现已得到改进,可以处理复杂多样的 Stdout 输出
○ vet 在并行运行的测试中可能会发生更多循环变量引用错误
○ 在没有 C 工具链 的系统上默认禁用 CGO
• 性能提升
○ 编译器和 GC 的优化减少了内存开销,并将 CPU 性能整体提高了 2%
○ 针对编译时间进行了优化,提升了 10%。使得构建速度与 Go 1.17 保持一致 (恢复到了泛型之前的速度)
○ Go 发行版瘦身,新版本起,Go 的 $GOROOT/pkg 目录将不再存储标准库的预编译包存档,Go 发行版的将迎来一轮瘦身
Go 1.19 重要的变化有
• Go 内存模型,详细参考官方文档:https://go.dev/ref/mem。随着内存模型的更新,Go 1.19 在 sync/atomic 包引入了新的类型:types Bool, Int32, Int64, Uint32, Uint64, Uintptr 和 Pointer 等,这让原子值的使用更方便。
• 工具方面,文档格式增强。文档注释中添加了对链接、列表和更清晰标题的支持。详情见:https://go.dev/doc/comment。
• runtime 方面,最值得关注的变化就是增加了 runtime/debug.SetMemoryLimit,可以限制 Go 的内存使用。其他是一些库的小变化。
详细变化可以查看官方 Release Notes: https://go.dev/doc/devel/release