Go 1.22 通关讲解

Go 1.22 通关讲解

介绍

Go 1.22 是继 Go 1.21 后的最新版本,主要集中在工具链、运行时和库的实现上进行了改进。这一版本保持了 Go 1 的兼容性承诺,因此几乎所有的 Go 程序都能够像以前一样进行编译和运行。

语言变更

1、在 Go 1.22 之前,"for" 循环中声明的变量只创建一次,并在每次迭代时更新。这可能会导致意外的共享错误。

以前的行为:

go 复制代码
func main() {
    values := []int{1, 2, 3, 4, 5}
    for _, v := range values {
        go func() {
            fmt.Println(v)
        }()
    }
    time.Sleep(time.Second * 1)
}

这段代码会输出 5 5 5 5 5 ,因为所有 goroutine 都捕获到了循环结束时 v 的值。

新的行为:

由于 goroutine 是并发执行的,因此它们可能会在不同的时间读取 v 变量的值。这会导致输出结果的顺序每次都不同。

以下是一些可能导致输出结果顺序不同的因素:

  • goroutine 调度的顺序
  • goroutine 执行的速度
  • CPU 的缓存
go 复制代码
2
3
1
4
5

注意

上面仅仅是我执行的结果你相信有点go语言基础的你会明白我在说什么。

使用 range 迭代数组

go 复制代码
func main() {
    values := []int{1, 2, 3, 4, 5}
    for _, v := range values {
        fmt.Println(v)
    }
}

这段代码将输出:

go 复制代码
1
2
3
4
5

使用 range 迭代字符串

go 复制代码
func main() {
    str := "Hello, world!"
    for _, r := range str {
        fmt.Println(r)
    }
}

这段代码将输出:

go 复制代码
H
e
l
l
o
,
 
w
o
r
l
d
!

2. "For" 循环现在可以迭代整数。例如:

go 复制代码
go package main 
import "fmt" 
func main() {
    for i := range 10 { 
          fmt.Println(10 - i) 
        } 
        fmt.Println("go1.22 已启动!") 
  } 

这段代码将输出:

go 复制代码
0
1
2
3
4

注意:

  • 在 Go 1.22 中,如果要使用循环变量的值,需要将其赋值给新的变量。(升级到新版本这点还是挺重要的)

例如:

go 复制代码
func main() {
    values := []int{1, 2, 3, 4, 5}
    for _, v := range values {
        // 将 v 赋值给新的变量 i


        i := v
        go func() {
            fmt.Println(i)
        }()
    }
    time.Sleep(time.Second * 1)
}

这段代码将输出:

go 复制代码
1
2
3
4
5

实验实践

看完上面的示例相信你已经打开编辑器想着尝试了,你可以选择以下方式来尝试1.22新特性

  • # Go语言多版本管理 -goenv 来安装新的版本来尝试对比
  • 还可以使用 Go 1.21 中的 GOEXPERIMENT=loopvar 实验性标志来体验 Go 1.22 中 "for" 循环变量的行为变更。

方法一:使用环境变量

  1. 在命令行中,设置 GOEXPERIMENT 环境变量为 loopvar:
linux 复制代码
export GOEXPERIMENT=loopvar
  1. 运行 Go 程序。

方法二:使用 go 命令

  1. 在命令行中,使用 go 命令的 -gcflags 标志设置 GOEXPERIMENT=loopvar:
linux 复制代码
go run -gcflags=-G=GOEXPERIMENT=loopvar main.go
  1. 运行 Go 程序。

取消设置环境变量

  1. 打开命令行。
  2. 运行以下命令取消设置 GOEXPERIMENT 环境变量:
linux 复制代码
unset GOEXPERIMENT

工具

Go 命令

  • 工作区中的命令现在可以使用包含工作区依赖项的 vendor 目录。当设置 -mod 标志为 vendor 时,构建命令将使用该目录。当存在工作区 vendor 目录时,此标志是默认设置。
  • 在遗留的 GOPATH 模式(即,GO111MODULE=off)下,不再支持 go get 命令。其他构建命令(如 go build 和 go test)将继续永久工作于遗留的 GOPATH 程序。

Trace

  • 跟踪工具的 Web UI 在支持新的跟踪器的过程中进行了轻微的更新,解决了一些问题,并改善了各个子页面的可读性。
  • Web UI 现在支持以线程为导向的视图探索跟踪。跟踪查看器现在还显示所有系统调用的完整持续时间。

Vet

  • vet 工具的行为已更改以匹配 Go 1.22 中的新语义。在分析需要 Go 1.22 或更新版本的文件时(由其 go.mod 文件或每个文件的构建约束),vet 不再报告来自函数文字内的循环变量的引用,这些引用可能会超出循环的迭代。
  • vet 工具现在报告调用 append 时未传递任何值的警告,例如 slice = append(slice)。这种语句没有效果,经验表明这几乎总是一个错误。
  • vet 工具现在报告在结构化日志包 log/slog 中调用函数和方法时出现的不匹配的键值对的警告。它报告关键位置的参数既不是字符串也不是 slog.Attr,并且缺少最后一个键的值。

运行时

  • 运行时现在将基于类型的垃圾回收元数据保存在每个堆对象附近,通过将 Go 程序的 CPU 性能(延迟或吞吐量)提高 1-3%。此更改还通过去重冗余元数据来减少大多数 Go 程序的内存开销约 1%。由于此更改调整了内存分配器的大小类边界,因此一些对象可能会移动到更大的大小类。一些使用需要内存地址始终对齐到 16 字节(或更高)边界的汇编指令的程序现在可能仅对齐到 8 字节边界。一些依赖内存分配器先前对齐行为的程序可能会中断,但我们预计此类程序很少。此类程序可以使用 GOEXPERIMENT=noallocheaders 进行构建,以恢复旧的元数据布局并恢复先前的对齐行为。
  • 在 windows/amd64 端口上,链接或加载使用 -buildmode=c-archive 或 -buildmode=c-shared 构建的 Go 库的程序现在可以使用 SetUnhandledExceptionFilter Win32 函数捕获 Go 运行时未处理的异常。注意,这在 windows/386 端口上已经受支持。

编译器

  • Profile-guided Optimization (PGO) 构建现在可以比以前更多地去虚拟化调用。大多数代表性 Go 程序集中的程序现在在运行时启用 PGO 后可以看到 2% 到 14% 的性能改进。
  • 编译器现在交错进行去虚拟化和内联,因此接口方法调用得到了更好的优化。
  • Go 1.22 还包括编译器内联阶段增强的早期实现,该实现针对长循环执行体内的间接调用进行了特殊处理。如果执行体是通过外部方法调用来自不同包的函数,则编译器会跟踪调用目标的类型信息,并在后续迭代中选择合适的具体实现进行内联。

  • math/bits 包现在提供了通过数字大小确定的查找表实现的 ReverseBytes 函数。例如,当 n <= 64 时,ReverseBytes32 和 ReverseBytes64 现在比使用算法实现的 ReverseBytes 更快。
  • regexp

包现在支持在 FindAll 和 FindSubmatch 方法中使用 -1 的范围参数。使用此范围参数,FindAll 和 FindSubmatch 将查找任意数量的重叠匹配项,而不仅仅是非重叠的匹配项。

  • time 包现在提供了一个代表 Unix 时间(1970 年 1 月 1 日 00:00:00 UTC)的常量。新的 UnixEpoch 常量可用于更好地表示此时间。

经典虚拟机

  • Go 1.22 现在支持在 GOOS=android 的 arm64 端口上交叉编译 Go 程序。在这种情况下,Go 命令将在以下方面假定目标系统与主机系统相同:字节序、页大小和 Go 运行时类型布局。如果需要,则仍可以通过适当的命令行标志来指定这些参数。
  • Go 1.22 还支持在 arm64 和 mips64 架构上的 32 位系统上构建 Go 程序。这是通过为 arm64、mips64 和 ppc64le 添加了对 android/arm、darwin/arm 和 linux/arm 的 cgo 支持实现的。

迁移说明

如果你想从 Go 1.21.x 迁移到 Go 1.22.x,请查看发行说明中的迁移说明

完整的发布说明

有关更新内容的详细信息,请参阅 Go 1.22 发布说明。

下载

可以从此处下载 Go 1.22 版本。

感谢整个 Go 社区的贡献!

这点非常重要请务必看完这句话

1.22 发布,建议评估后升级,关注主项目风险,可选择试用或部分升级。

相关推荐
IT邦德2 小时前
GoldenGate 19C的静默安装及打补丁
数据库
黎雁·泠崖2 小时前
指针家族高阶篇:字符指针、数组指针、函数指针及转移表应用
c语言·开发语言
小年糕是糕手2 小时前
【C/C++刷题集】string类(一)
开发语言·数据结构·c++·算法·leetcode
a努力。2 小时前
国家电网Java面试被问:二叉树的前序、中序、后序遍历
java·开发语言·后端·面试
JAVA+C语言2 小时前
C++ 继承与派生
开发语言·c++
yuniko-n2 小时前
【力扣 SQL 50】子查询篇
数据库·sql·leetcode
fiveym2 小时前
PXE启动菜单配置完全指南:打造高效网络装机入口
开发语言·网络·php
chao1898442 小时前
基于MATLAB实现NSGA-II算法
开发语言·算法·matlab
未来之窗软件服务2 小时前
幽冥大陆(五十七)ASR whisper-cli命令行使用 C语言—东方仙盟筑基期
c语言·开发语言·whisper·仙盟创梦ide·东方仙盟·东方仙盟自动化·东方仙盟商业开发