Go1.21.0 到 Go1.23.0 的改动,向前兼容性和toolchain规则,Go1.21.0,必须升级你的Go啦

news2024/12/24 17:50:51

Go各版本Release Note

Go1.21.0

2023-08-08

https://go.dev/doc/go1.21

内置方法

min & max:返回一个序列中的最大值最小值。

https://go.dev/ref/spec#Min_and_max

clear:清空map和slice。

https://go.dev/ref/spec#Clear

标准库

log/slog

The new log/slog package provides structured logging with levels. Structured logging emits key-value pairs to enable fast, accurate processing of large amounts of log data. The package supports integration with popular log analysis tools and services.

testing/slogtest

The new testing/slogtest package can help to validate slog.Handler implementations.

slices

The new slices package provides many common operations on slices, using generic functions that work with slices of any element type.

maps

The new maps package provides several common operations on maps, using generic functions that work with maps of any key or element type.

cmp

The new cmp package defines the type constraint Ordered and two new generic functions Less and Compare that are useful with ordered types.

toolchain

Go工具链管理,以及Go版本匹配规则。下文说到。

Go1.22

2024-02-06

1、修复 for 循环变量的错误

在此之前的写法

func main() {
	for i := 0; i < 5; i++ {
        v := i
		wg.Add(1)
		go func() {
			defer wg.Done()
			fmt.Println(v)
		}()
	}

	wg.Wait()
}

现在的写法

func main() {
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			fmt.Println(i)
		}()
	}

	wg.Wait()
}

2、range可以遍历整数

for i := range 10 {
    fmt.Println(10 - i)
}

3、标准库

math/rand/v2

https://go.dev/pkg/math/rand/v2/

go/version

The new go/version package implements functions for validating and comparing Go version strings.

Go1.23

2024-08-13

for-range 循环中的范围表达式现在可以是迭代器函数,例如 func(func(K) bool),这支持了用户对任意序列自定义迭代器。同时,slices 和 maps 包新增了一些与迭代器配合使用的功能,还新增了一个 iter 包。比如可以轻松地将 map 的键收集到切片中并对其值进行排序。

Range Over Function Types

标准库

1、对 time.Timer 和 time.Ticker 做了重大改动,与老的写法不兼容,鉴于Go的工具链管理,升级之后并不会对之前的项目构成影响,前提是你依旧按照原先的版本编译。

https://go.dev/doc/go1.23#library

首先,程序不再引用的计时器和 Tickers 立即有资格使用垃圾回收机制,即使它们的 Stop 方法没有被调用。早期版本的 Go 直到发射后才收集未停止的计时器,并且从未收集未停止的 Tickers。

其次,与 Timer 或 Ticker 关联的计时器通道现在是无缓冲的,容量为 0。此更改的主要效果是 Go 现在保证对于对 Reset 或 Stop 方法的任何调用,不会在调用后发送或接收在该调用之前准备的陈旧值。Go 的早期版本使用带有单元素缓冲区的通道,因此很难正确使用 Reset 和 Stop。此更改的一个明显效果是计时器通道的 len 和 Cap 现在返回 0 而不是 1,这可能会影响轮询长度以决定计时器通道上的接收是否会成功的程序。此类代码应使用非阻塞接收代替。

特别说明,当你的go.mod的go行大宇等于1.23.0,此项特性才会生效。当你用Go1.23编译老代码时,此特性不会生效。

2、增加了 unique 包

3、Iterators包

4、structs包

The new structs package provides types for struct fields that modify properties of the containing struct type such as memory layout.

向前兼容性

在以前的版本中,Go 工具链尝试编译依赖于新版本的代码时,可能会遇到兼容性问题。例如,如果你的代码依赖于 Go 1.18 引入的新特性,使用小于这个本本版本的 Go 编译器将会导致编译错误。但是,这些错误信息有时并不直观,可能仅仅显示为语法错误,而实际上是由于工具链版本不匹配。

在 Go 1.21 中,工具链会严格遵循 go.mod 文件中的版本声明。例如,如果你的 go.mod 文件中声明了 go 1.21.1,那么 Go 1.21.0 将无法编译这段代码。这种方式有效地避免了潜在的编译错误。

工具链管理

为了减少强制版本匹配对开发者的影响,Go 1.21 还引入了工具链管理功能,使得你可以为不同的项目指定不同的工具链版本。这一功能类似于 Node 的 nvm 或 Rust 的 rustup,但它是内置于 Go 的核心工具中。

// go.mod 文件
module example

go 1.21.0
toolchain go1.21.4

在上面的配置中,toolchain go1.21.4 指定了在当前模块中需要使用 Go 1.21.4 工具链。Go 命令会自动下载并使用指定的工具链版本,而无需手动干预。

更新 go.mod 中的 go 行:

go get go@1.21.0,该命令将下载并切换到 Go 1.21.0 版本,并自动更新 go 行。

如果你希望在保持旧版本 go 行不变的情况下更新工具链,可以使用:go get toolchain@go1.21.0。工具链就是run/build/link等等工具。

强制使用特定工具链版本

你可以通过 GOTOOLCHAIN 环境变量来强制使用特定版本的 Go 工具链。

关于环境变量,分为临时的(会话级别的)和永久生效的,优先级临时>永久.

# 查看
go env GOTOOLCHAIN

# 设置永久生效(不推荐)
go env -w GOTOOLCHAIN=go1.20

# windows系统,设置临时
set GOTOOLCHAIN=go1.20

# Linux系统,直接放在命令开头即可
# windows系统不支持这种写法
GOTOOLCHAIN=go1.20 go run main.go

可以理解为在 Go 1.21 以前,我们用的是GOTOOLCHAIN=local,即使用你本地安装的Go版本。

在 Go 1.21 之后,如果Go发现本地工具链版本低于go mod要求的最低版本,那么Go会自动下载匹配的Go工具链,缓存到go module cache(不会覆盖本地安装的go工具链),保存在 pkg/mod 目录下,就像你下载普通的依赖一样,并用新下载的Go工具链对module进行编译构建。

也就是说,你本地现在可以有多个版本的Go工具链,主版本就是你的安装版本,其他的版本就是用来编译。

有时候你可能有多个项目,它们依赖不同的Go版本。

go xxx 就是初始化项目的时候你本地安装的Go版本。

toolchain goxxx 是编译时要求使用的Go版本,出现这种情况,可能是依赖的第三方包要求的Go版本高于你本地安装的版本。

这就是所谓的向前兼容性,开发者可以放心使用新语言特性,无需担心旧版本编译器带来的问题,go命令会自动处理这一切

自动升级工具链

你还可以设置自动升级工具链版本。使用 GOTOOLCHAIN 环境变量的形式 version+auto 可以在保留当前版本的同时允许自动升级。例如:go env -w GOTOOLCHAIN=go1.21.1+auto

当 Go 1.21.1 发布时,你的系统将自动使用该版本。

Go 1.21 的工具链管理功能和向前兼容性改进将大大提升 Go 开发的便利性。通过这些新特性,你可以更好地管理不同版本的工具链,确保代码在不同版本的 Go 中稳定运行。

那么你如何知道Go到底会使用哪个版本编译呢?

方法1:go version

在 go env 的输出中,如果 GOTOOLCHAIN=auto,那么 GOVERSION 的值一般就是安装的Go版本。

终端1:

go env GOTOOLCHAIN
auto

go env GOVERSION
go1.23.4

go version
go version go1.23.4 windows/amd64

如果设置 GOTOOLCHAIN=go1.20,那么 GOTOOLCHAIN 和 GOVERSION 的值就是一样的。

终端2:

# 设置临时环境变量,只在当前命令行生效
set GOTOOLCHAIN=go1.20

go env GOTOOLCHAIN
go1.20

go env GOVERSION
go1.20

go version
go version go1.20 windows/amd64

go version的值就是 go env GOVERSION的值,也就是说 go version 的确可以预示着会使用哪个版本的Go编译此项目。但是 go version 只是检查到了环境变量这一层,并不会检查go.mod中的toolchain行。

方法2:-x 参数

go run -x main.go
go build -x main.go

会打印出执行过程,能看到使用的是哪个工具链。

终端1:

go run -x main.go

mkdir -p $WORK\b001\exe\
cd .
GOROOT='D:\Go' "D:\\Go\\pkg\\tool\\windows_amd64\\link.exe" -o "$WORK\\b001\\exe\\main.exe".......

终端2:

set GOTOOLCHAIN=go1.20

go run -x main.go

mkdir -p $WORK\b001\exe\
cd .
"D:\\dev\\php\\magook\\trunk\\server\\golang\\path\\pkg\\mod\\golang.org\\toolchain@v0.0.1-go1.20.windows-amd64\\pkg\\tool\\windows_amd64\\link.exe" -o "$WORK\\b001\\exe\\main.exe".......

从结果来看的确是使用了不同版本的工具。

多个版本的Go被保存在PATH/pkg/mod/golang.org/toolchain@v0.0.1-goxxxxx。

Go命令选择版本的规则是什么?

toolchain 行一定要大于等于 go1.21.0,否则会报错,然后 toolchain 行可以大于 go 行,也可以小于 go 行,不会报错。

Go命令会先比较 toolchain 行和 go 行,取大的,然后与本地安装版本比较,取大的,如果结果大于本地版本,才会下载使用新的版本,否则只会使用本地版本,Go保证高版本可以正常编译低版本。

如果你引入的第三方包要求的版本大于go.mod中的go行,且大于本地安装版本,会自动为你加上 toolchain goxxx

在 go1.21.0 之后,go 行,toolchain 行,GOTOOLCHAIN都要精确到三级版本号,否则会报错。

升级到Go1.23.4

把Go升级到大于等于1.21.0已经是不得不做的事情,因为未来很多第三方包会依赖于1.21.0及其以上,而你的项目将无法使用它们,但是这又不是绝对的,在1.20的时候我的项目依赖了1.21.4的包,windows平台可以正常编译,但是darwin则无法编译。

windows系统直接下载msi安装包安装即可。

Linux下载tar.gz直接覆盖即可。

如果不想覆盖只想体验下新版本:go install golang.org/dl/go1.23.0@latest 只会下载Go的可执行文件到 $GOPATH/bin/go1.23.4.exe,并不算版本更新。

Windows系统设置环境变量

在这里插入图片描述

GOSUMDB需要设置,因为如果触发了下载其他版本,就进行校验,如果目标地址设置错误就会报错

go: downloading go1.20 (linux/amd64)
go: download go1.20: golang.org/toolchain@v0.0.1-go1.20.linux-amd64: verifying module: invalid GOSUMDB: malformed verifier id

因为我的项目大多在1.20版本,所以我需要测试一下有没有问题。

一个简单的测试项目go-new

util
	util.go
go.mod
main.go
// go.mod

module go-new

go 1.20
// main.go

package main

import (
	"fmt"
	"go-new/util"
)

func main() {
	fmt.Println(util.Max(1, 2))
}
set GOTOOLCHAIN=go1.20

go run main.go

main.go:5:2: ambiguous import: found package go-new/util in multiple modules:
        go-new (D:\dev\php\magook\trunk\server\go-new\util)
         (D:\dev\php\magook\trunk\server\golang\path\pkg\mod\golang.org\toolchain@v0.0.1-go1.20.windows-amd64\src\go-new\util)
set GOTOOLCHAIN=go1.19

go run main.go

main.go:5:2: cannot find package "go-new/util" in:
        D:\dev\php\magook\trunk\server\golang\path\pkg\mod\golang.org\toolchain@v0.0.1-go1.19.windows-amd64\src\go-new\util
set GOTOOLCHAIN=go1.18

go run main.go

可以正常运行

修改 go.mod

module go-new

go 1.21.0
set GOTOOLCHAIN=go1.21.0

go run main.go

可以正常运行
set GOTOOLCHAIN=go1.22.0

go run main.go

可以正常运行

由此可见,GOTOOLCHAIN 在低于 1.21.0的时候存在兼容性问题,这意味着,当我升级到Go1.23.4的时候,我过往的项目(依赖于Go1.20及其以下)应该在Go1.21.0版本运行,但是,如果你信任Go官方的话,这些都不需要。

如果我一直停留在Go1.23.4,随着时间的推移,有些第三方包会依赖更高版本的Go,到时候可以用go.mod中的toolchain行来解决,这个会自动被添加上的,不需要操心。

阅读Go的release note可以发现Go基本是保证向前兼容,其新特性是以增量的方式加入的,而不会改变以前版本的特性,但并不代表你可以不关心了,比如上面提到的在Go1.23.0中的time.Timer的特性改动,如果你升级到了1.23但是并不了解其变化而依旧使用之前的方式来编码,结果可能会超出你的认知,导致严重的后果。

在 Go 1.21 之后我们要分清楚几个概念

  • go命令,它与Go版本无关(或淡化),就是个命令。
  • go.mod 中的 go 行,是当前模块开发时的版本要求。
  • go.mod 中的 toolchain 行,是依赖的第三方包的版本要求。
  • 不同版本的Go会像普通的依赖包一样同时存在。
总结

说了那么多,升级到新版本后,我该注意些什么呢?答案是什么也不用。

基于Go的新版本都是增量发布的,不会改变旧的逻辑,即便是不得不大改的time.Timer,Go也会根据go.mod中go行来区别对待,所以我们不要改动go行。放心的使用Go1.23.4来编译Go1.20的项目。

参考

Forward Compatibility and Toolchain Management in Go 1.21

Go Toolchains

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2264850.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot472基于web网上村委会业务办理系统(论文+源码)_kaic

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本网上村委会业务办理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数…

数据库压力测试详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 很多人提到 jmeter 时&#xff0c;只会说到 jmeter进行接口自动化或接口性能测试&#xff0c;其实jmeter还能对数据库进行自动化操作。个人常用的场景有以下&#…

深度学习中,用损失的均值或者总和反向传播的区别

如深度学习中代码&#xff1a; def train_epoch_ch3(net, train_iter, loss, updater):"""The training loop defined in Chapter 3."""# Set the model to training modeif isinstance(net, torch.nn.Module):net.train()# Sum of training lo…

UML图【重要】

文章目录 2.1 类图概述2.2 类图的作用2.3 类图表示法2.3.1 类的表示方式2.3.2 类与类之间关系的表示方式2.3.2.1 关联关系2.3.2.2 聚合关系2.3.2.3 组合关系2.3.2.4 依赖关系2.3.2.5 继承关系2.3.2.6 实现关系 统一建模语言&#xff08;Unified Modeling Language&#xff0c;U…

Flask中@app.route()的methods参数详解

诸神缄默不语-个人CSDN博文目录 在 Flask 中&#xff0c;app.route 是用于定义路由的核心装饰器&#xff0c;开发者可以通过它为应用指定 URL 映射及相应的处理函数。在处理 HTTP 请求时&#xff0c;不同的业务场景需要支持不同的 HTTP 方法&#xff0c;而 app.route 的 metho…

JavaSE---String(含一些源码)

&#xff08;一&#xff09;字符串构造 我们如何创建一个String类型的对象&#xff1f;有三种&#xff1a; String s1new String("hello"); //直接new一个String对象String s2"hello"; //使用常量串构造final char[] chars {h,e,l,l,o}; Strin…

0.96寸OLED显示屏详解

我们之前讲了 LCD1602&#xff0c;今天我们将它的进阶模块——OLED。它接线更少&#xff0c;性能更强&#xff0c;也能显示中文和图像了。 大家在学习单片机的时候是否会遇到调试的问题呢&#xff1f;例如 “这串代码我到底运行成功了没有” &#xff0c;我相信很多刚开始学习…

用un-app写的动漫风格的登录界面

动漫风格的的登录、注册界面模板&#xff0c;使用uni-app编写&#xff0c;直接复制粘贴即可。 废话不多说&#xff0c;代码如下&#xff1a; login.vue文件 <template><view class"content"><view class"tab-box"><text class"c…

Pytorch | 从零构建ParNet/Non-Deep Networks对CIFAR10进行分类

Pytorch | 从零构建ParNet/Non-Deep Networks对CIFAR10进行分类 CIFAR10数据集ParNet架构特点优势应用 ParNet结构代码详解结构代码代码详解SSEParNetBlock 类DownsamplingBlock 类FusionBlock 类ParNet 类 训练过程和测试结果代码汇总parnet.pytrain.pytest.py 前面文章我们构…

【服务器】linux服务器管理员查看用户使用内存情况

【服务器】linux服务器管理员查看用户使用硬盘内存情况 1、查看所有硬盘内存使用情况 df -h2、查看硬盘挂载目录下所有用户内存使用情况 du -sh /public/*3、查看某个用户所有文件夹占用硬盘内存情况 du -sh /public/zhangsan/*

[搜广推]王树森推荐系统——其他召回通道

地理位置召回 GeoHash召回 想法&#xff1a;用户可能对附近发生的事感兴趣 方法&#xff1a;对经纬度的编码&#xff0c;地图上一个长方形区域 索引&#xff1a;GeoHash -> 优质笔记列表(按时间倒排) 这条召回通道没有个性化 同城召回 想法&#xff1a;用户可能对同…

重温设计模式--外观模式

文章目录 外观模式&#xff08;Facade Pattern&#xff09;概述定义 外观模式UML图作用 外观模式的结构C 代码示例1C代码示例2总结 外观模式&#xff08;Facade Pattern&#xff09;概述 定义 外观模式是一种结构型设计模式&#xff0c;它为子系统中的一组接口提供了一个统一…

OpenCV学习——图像融合

import cv2 as cv import cv2 as cvbg cv.imread("test_images/background.jpg", cv.IMREAD_COLOR) fg cv.imread("test_images/forground.png", cv.IMREAD_COLOR)# 打印图片尺寸 print(bg.shape) print(fg.shape)resize_size (1200, 800)bg cv.resize…

ECharts热力图-笛卡尔坐标系上的热力图,附视频讲解与代码下载

引言&#xff1a; 热力图&#xff08;Heatmap&#xff09;是一种数据可视化技术&#xff0c;它通过颜色的深浅变化来表示数据在不同区域的分布密集程度。在二维平面上&#xff0c;热力图将数据值映射为颜色&#xff0c;通常颜色越深表示数据值越大&#xff0c;颜色越浅表示数…

进程间关系与守护进程

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 进程间关系与守护进程 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. 进程组 什…

LightGBM分类算法在医疗数据挖掘中的深度探索与应用创新(上)

一、引言 1.1 医疗数据挖掘的重要性与挑战 在当今数字化医疗时代,医疗数据呈爆炸式增长,这些数据蕴含着丰富的信息,对医疗决策具有极为重要的意义。通过对医疗数据的深入挖掘,可以发现潜在的疾病模式、治疗效果关联以及患者的健康风险因素,从而为精准医疗、个性化治疗方…

【文档搜索引擎】缓冲区优化和索引模块小结

开机之后&#xff0c;首次制作索引会非常慢&#xff0c;但后面就会快了 重启机器&#xff0c;第一次制作又会非常慢 这是为什么呢&#xff1f; 在 parserContent 里面&#xff0c;我们进行了一个读文件的操作 计算机读取文件&#xff0c;是一个开销比较大的操作&#xff0c; …

html+css网页设计 旅游 移动端 雪花旅行社4个页面

htmlcss网页设计 旅游 移动端 雪花旅行社4个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 …

3 JDK 常见的包和BIO,NIO,AIO

JDK常见的包 java.lang:系统基础类 java.io:文件操作相关类&#xff0c;比如文件操作 java.nio:为了完善io包中的功能&#xff0c;提高io性能而写的一个新包 java.net:网络相关的包 java.util:java辅助类&#xff0c;特别是集合类 java.sql:数据库操作类 IO流 按照流的流向分…

从零创建一个 Django 项目

1. 准备环境 在开始之前&#xff0c;确保你的开发环境满足以下要求&#xff1a; 安装了 Python (推荐 3.8 或更高版本)。安装 pip 包管理工具。如果要使用 MySQL 或 PostgreSQL&#xff0c;确保对应的数据库已安装。 创建虚拟环境 在项目目录中创建并激活虚拟环境&#xff…