当前位置: 首页 > news >正文

Golang的for循环变量和goroutine的陷阱,1.22版本的更新

先来看一段golang 1.22版本之前的for循环的代码

package mainimport "fmt"func main() {done := make(chan bool)values := []string{"chen", "hai", "feng"}for _, v := range values {fmt.Println("start")go func() {fmt.Println(v)done <- true}()fmt.Println("end")}for _ = range values {<-done}
}

运行结果

输出的都是最后的"feng"

在for循环体里,匿名函数和循环变量v形成了闭包。循环变量v只会创建一次,每次迭代都会更新。而且这样的写法会导致for循环结束后才执行goroutine代码,这时候变量v里保存的是最后一个值,所以这里会输出"feng"。

以下提供两种常用的正确写法

第一种方法是在匿名函数中添加参数val,每个val都会被独立计算并保存到goroutine的栈中,所以可以达到预期的结果

package mainimport "fmt"func main() {done := make(chan bool)values := []string{"chen", "hai", "feng"}for _, v := range values {fmt.Println("start")go func(val interface{}) {fmt.Println(val)done <- true}(v)fmt.Println("end")}for _ = range values {<-done}
}

此时的运行结果

第二种写法:在for循环体内定义新的变量。循环体内定义的变量在遍历的过程中是不共享的,所以可以达到期望的效果。

package mainimport "fmt"func main() {done := make(chan bool)values := []string{"chen", "hai", "feng"}for _, v := range values {fmt.Println("start")val := vgo func() {fmt.Println(val)done <- true}()fmt.Println("end")}for _ = range values {<-done}
}

此时的运行结果

升级到最新版本1.22,同样的代码

package mainimport "fmt"func main() {done := make(chan bool)values := []string{"chen", "hai", "feng"}for _, v := range values {fmt.Println("start")go func() {fmt.Println(v)done <- true}()fmt.Println("end")}for _ = range values {<-done}
}

现在运行结果如下

在golang 1.22中,循环的每次迭代都会创建新的变量,有效避免了以往版本中常见的闭包陷阱,提高了代码的安全性。

另外,1.22之前的版本,for range仅支持array, slice, string, map, channel等类型,现在新增了interger类型,这意味着我们可以像这样写代码

package mainimport "fmt"func main() {for i := range 10 {fmt.Println(i)}
}

 

相关文章:

  • Springboot项目报文加密(AES、RSA、Filter动态加密)
  • 【开源】SpringBoot框架开发天沐瑜伽馆管理系统
  • MongoDB聚合:$listSampledQueries
  • [C# WPF] DataGrid选中行或选中单元格的背景和字体颜色修改
  • 【C语言】assert断言:保护程序的利器
  • 车载电子电器架构 —— 电子电气系统车载功能子系统
  • 【漏洞复现】多语言药房管理系统MPMS文件上传漏洞
  • 2024-02-11 Unity 编辑器开发之编辑器拓展2 —— 自定义窗口
  • mxxWechatBot基本配置
  • .NetCore 如何动态路由
  • leetcode链表相关题目
  • 树状菜单(利用映射-bootstrap+jQuery实现折叠功能)
  • 单片机学习笔记---蜂鸣器播放提示音音乐(天空之城)
  • Unity2D 学习笔记 0.Unity需要记住的常用知识
  • Vue中路由的使用
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • Docker 笔记(2):Dockerfile
  • ES6之路之模块详解
  • flutter的key在widget list的作用以及必要性
  • Invalidate和postInvalidate的区别
  • java8 Stream Pipelines 浅析
  • log4j2输出到kafka
  • miaov-React 最佳入门
  • MobX
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • SwizzleMethod 黑魔法
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • underscore源码剖析之整体架构
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • Yeoman_Bower_Grunt
  • 从零开始在ubuntu上搭建node开发环境
  • 反思总结然后整装待发
  • 观察者模式实现非直接耦合
  • 离散点最小(凸)包围边界查找
  • 聊聊directory traversal attack
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 深入浅出webpack学习(1)--核心概念
  • 算法之不定期更新(一)(2018-04-12)
  • 再次简单明了总结flex布局,一看就懂...
  • Java总结 - String - 这篇请使劲喷我
  • postgresql行列转换函数
  • ​​​​​​​​​​​​​​Γ函数
  • ​Java并发新构件之Exchanger
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • (04)odoo视图操作
  • (06)金属布线——为半导体注入生命的连接
  • (3)(3.5) 遥测无线电区域条例
  • (C语言)fgets与fputs函数详解
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (第27天)Oracle 数据泵转换分区表
  • (十五)使用Nexus创建Maven私服
  • (算法)Travel Information Center
  • (算法)求1到1亿间的质数或素数
  • (一)Java算法:二分查找