go中for range的坑以及解决方案

 更新时间:2024年01月12日 08:52:16   作者:fbbqt  
相信小伙伴都遇到过以下的循环变量的问题,本文主要介绍了go中for range的坑以及解决方案,具有一定的参考价值,感兴趣的可以了解一下

一、for range的坑

相信小伙伴都遇到过以下的循环变量的问题,那是因为循环的val变量是重复使用的,即仅有一份。也就是说,每次循环后赋给val的值就会把前面循环赋给val的值替换掉,所以打印出来的值都是最后一次循环赋给val的值。

1、例子

func fr1() {
	arr := []int{1, 2, 3}
	for _, val := range arr {
		go func() {
            time.Sleep(time.Millisecond * 100)
			fmt.Println(val)
		}()
	}
	time.Sleep(time.Second)
}
//输出结果:3 3 3 


func fr2() {
	arr := [2]int{1, 2}
	arrnew := []*int{}
	for _, val := range arr {
		arrnew = append(arrnew, &v)
	}

	fmt.Println(*arrnew[0], *arrnew[1])
	//输出结果: 2 2
}

2、解决方案

使用局部变量/临时变量,即可解决

func fr1() {
	values := []int{1, 2, 3, 4, 5}
	for _, val := range values {
        //在这加入临时变量
		val := val 
		go func() {
			time.Sleep(time.Millisecond * 100)
			fmt.Println(val)
		}()
	}
	time.Sleep(time.Second)
}
//输出结果:2 3 1 4 5 或 5 3 4 1 2 等无序结果


//===========================或者=============================

func fr1() {
	values := []int{1, 2, 3, 4, 5}
	for _, val := range values {
        //传入变量
		go func(val int) {
			time.Sleep(time.Millisecond * 100)
			fmt.Println(val)
		}(val)
	}
	time.Sleep(time.Second)
}
//输出结果:2 3 1 4 5 或 5 3 4 1 2 等无序结果

二、官方解决方案

1、在Go1.21版本中,提前体验

可以设置 GOEXPERIMENT=loopvar,就会解决以上问题,运行代码时就不会出现以上的坑。

Windows中设置举例

go env -w GOEXPERIMENT=loopvar
或
$env:GOEXPERIMENT="loopvar"
> go env
set GO111MODULE=on
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\Administrator\AppData\Local\go-build
set GOENV=C:\Users\Administrator\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=loopvar
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\Administrator\go\pkg\mod

2、预计在 Go1.22 起,在go.mod中支持

新的 for 循环语义,将会在 go.mod 文件中的 go 行(版本声明大于等于 Go1.22 下)默认应用也就不用设置 GOEXPERIMENT=loopvar 

到此这篇关于go中for range的坑以及解决方案的文章就介绍到这了,更多相关go for range坑内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • GoFrame框架数据校验之校验结果Error接口对象

    GoFrame框架数据校验之校验结果Error接口对象

    这篇文章主要为大家介绍了GoFrame框架数据校验之校验结果Error接口对象示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • golang MarshalJson的实现

    golang MarshalJson的实现

    本文主要介绍了golang MarshalJson的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-03-03
  • golang mapstructure库的具体使用

    golang mapstructure库的具体使用

    mapstructure用于将通用的map[string]interface{}解码到对应的 Go 结构体中,或者执行相反的操作,本文主要介绍了golang mapstructure库的具体使用,感兴趣的可以了解一下
    2023-09-09
  • go语言中线程池的实现

    go语言中线程池的实现

    Go语言中并没有直接类似 Java 线程池的内建概念,主要通过goroutine和channel来实现并发处理,本文主要介绍了go语言中线程池的实现,具有一定的参考价值,感兴趣的可以了解一下
    2025-04-04
  • Go基础Slice教程详解

    Go基础Slice教程详解

    这篇文章主要介绍了Go基础Slice教程详解,需要的朋友可以参考下
    2018-02-02
  • 基于Go语言实现简单的计算器

    基于Go语言实现简单的计算器

    这篇文章主要为大家详细介绍了如何基于Go语言实现简单的计算器,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以跟随小编一起了解一下
    2023-10-10
  • Go开发环境搭建详细介绍

    Go开发环境搭建详细介绍

    由于目前网上Go的开发环境搭建文章很多,有些比较老旧,都是基于 GOPATH的,给新入门的同学造成困扰。以下为2023 版 Go 开发环境搭建,可参照此教程搭建Go开发环境,有需要的朋友可以参考阅读
    2023-04-04
  • 详解Go语言中的Slice链式操作

    详解Go语言中的Slice链式操作

    这篇文章主要为大家详细介绍了Go语言中的Slice链式操作的相关知识,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-04-04
  • Golang泛型实现类型转换的方法实例

    Golang泛型实现类型转换的方法实例

    将一个值从一种类型转换到另一种类型,便发生了类型转换,下面这篇文章主要给大家介绍了关于Golang泛型实现类型转换的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • 对Golang import 导入包语法详解

    对Golang import 导入包语法详解

    今天小编就为大家分享一篇对Golang import 导入包语法详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-06-06

最新评论