您现在的位置是:首页 > 编程 > 

Go1.22 For 循环重大更新!注意defer函数!

2025-07-26 21:17:36
Go1.22 For 循环重大更新!注意defer函数! Golang 语言现在越来越受欢迎,尤其在云计算领域。其中For 循环以及defer更是被经常使用,可以说是必用。长话短说,看下面的代码。代码语言:javascript代码运行次数:0运行复制jiazha-mac:bin jiazha$ cat main.go package main import ( "fmt"

Go1.22 For 循环重大更新!注意defer函数!

Golang 语言现在越来越受欢迎,尤其在云计算领域。其中For 循环以及defer更是被经常使用,可以说是必用。长话短说,看下面的代码。

代码语言:javascript代码运行次数:0运行复制
jiazha-mac:bin jiazha$ cat main.go 
package main

import (
  "fmt"
)

type projectDescription struct {
  name            string
  targetamespace string
}

func (p *projectDescription) test() {
  fmt.Println()
}

func main() {
  projects := []projectDescription{
    {name: "openshifttest", targetamespace: ""},
    {name: "openshift-test1", targetamespace: ""},
    {name: "openshift-test2", targetamespace: ""},
    {name: "default", targetamespace: ""},
    {name: "openshift-test", targetamespace: ""},
    {name: "openshift-operators", targetamespace: ""},
  }
  for _, project := range projects {
    if  != "default" &&  != "openshift-operators" {
      defer ()
    }
  }
}

给自己几分钟,思考下结果该是什么。

有人会说,输出如下:

代码语言:javascript代码运行次数:0运行复制
openshift-test
openshift-test2
openshift-test1
openshifttest

那估计你是从go1.22 开始学习使用的,或者你是忽略了指针,或者你初用Golang。而有的人会说,不对,应该是:

代码语言:javascript代码运行次数:0运行复制
openshift-operators
openshift-operators
openshift-operators
openshift-operators

那么恭喜你,你对指针,for循环,defer理解透彻了。

那么到底谁说的对呢?答案是都对!使用不同的Golang版本,输出不同!从go1.22 之后第一种说法是对的;go1.22之前第二种说法是对的。来看下运行结果,Go1.22 之前:

代码语言:javascript代码运行次数:0运行复制
jiazha-mac:bin jiazha$ ./go version
go version go1.20.1 darwin/arm64
jiazha-mac:bin jiazha$ ./go run main.go
openshift-operators
openshift-operators
openshift-operators
openshift-operators

jiazha-mac:bin jiazha$ ./go version
go version go1.21.9 darwin/arm64
jiazha-mac:bin jiazha$ ./go run main.go
openshift-operators
openshift-operators
openshift-operators
openshift-operators

Go1.22:

代码语言:javascript代码运行次数:0运行复制
jiazha-mac:bin jiazha$ go version
go version go1.22.6 darwin/arm64

jiazha-mac:bin jiazha$ go run main.go 
openshift-test
openshift-test2
openshift-test1
openshifttest

那么这到底是什么原因导致的呢?原因是 Go1.22 对于 For 循环的更新:以前,“for”循环声明的变量只创建一次,每次迭代都会更新。在 Go 1.22 中,循环的每次迭代都会创建新变量,以避免意外共享错误。Go官方文档:/doc/go1.22#language

代码语言:javascript代码运行次数:0运行复制
  for _, project := range projects {
    if  != "default" &&  != "openshift-operators" {
      defer ()
    }
  }

再来看代码,在Go 语言中,函数的参数传递只有值传递,而且传递的实参都是原始数据的一份拷贝!defer 函数也是值传递,但是在这个代码里,方法的接受者是指针,虽然传递的是副本,但它是地址的副本,所以defer 中存储的是地址!

代码语言:javascript代码运行次数:0运行复制
func (p *projectDescription) test() {
  fmt.Println()
}

在for 循环结束后,defer开始运行,那么这时候 project 变量指向的地址中存储的值已经是 openshift-operators了,所以会打印4个operator-operators.

在Go1.22 中,每次迭代,都会创建新的变量,,所以defer 中存储的是四个不同的地址,每个地址指向不同的值,也就是打印出 openshift-test,openshift-test2,openshift-test1, openshifttest.

那么该如何让代码在不同的go 版本中都能打印出期望的输出呢:

代码语言:javascript代码运行次数:0运行复制
openshift-test
openshift-test2
openshift-test1
openshifttest

方法一:不要使用指针,直接传递值,那么defer中存储的就是不同的值。

代码语言:javascript代码运行次数:0运行复制
func (p projectDescription) test() {
  fmt.Println()
}

方法二:每次迭代赋值新的变量,那么test方法中存储的就是不同的地址,指向不同的值。

代码语言:javascript代码运行次数:0运行复制
        for _, pro := range projects {
                project := pro
                if  != "default" &&  != "openshift-operators" {
                        defer ()
                }
        }

方法三:使用闭包函数:

代码语言:javascript代码运行次数:0运行复制
  for _, project := range projects {
    if  != "default" &&  != "openshift-operators" {
      defer func(p projectDescription) {
        ()
      }(project)
   }

你还有其它的方法吗?欢迎留言讨论!

本文参与 腾讯云自媒体同步曝光计划,分享自。原始发表:2024-11-28,如有侵权请联系 cloudcommunity@tencent 删除存储openshift变量函数指针

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1143889.html

相关标签:无
上传时间: 2025-07-19 09:52:46
留言与评论(共有 5 条评论)
本站网友 迪拜帆船酒店
10分钟前 发表
但它是地址的副本
本站网友 抽脂抽脂手术
18分钟前 发表
= range projects { if != "default" && != "openshift-operators" { defer func(p projectDescription) { () }(project) }你还有其它的方法吗?欢迎留言讨论!本文参与 腾讯云自媒体同步曝光计划
本站网友 花体字
14分钟前 发表
targetamespace
本站网友 sockscap
30分钟前 发表
应该是