当前位置: 首页 > 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)}
}

 

http://www.lryc.cn/news/296815.html

相关文章:

  • List 差集
  • ArcGIS的UTM与高斯-克吕格投影分带要点总结
  • 华为第二批难题一:基于预训练AI模型的元件库生成
  • Android AOSP源码研究之万事开头难----经验教训记录
  • 动态数据源
  • 2024.1.29力扣每日一题——自由之路
  • Qt应用软件【协议篇】UDP示例
  • MyBatis之动态代理实现增删改查以及MyBatis-config.xml中读取DB信息文件和SQL中JavaBean别名配置
  • 百面嵌入式专栏(面试题)内存管理相关面试题1.0
  • SpringMVC 1.请求参数检查 2.全局异常处理 3.请求参数封装为Pojo
  • 7机器人位姿的数学描述与坐标变
  • 基于ESP8266 开发板(MCU)遥控小车
  • 【C生万物】C语言数据类型、变量和运算符
  • CTF--Web安全--SQL注入之‘绕过方法’
  • 线程池常用的阻塞队列
  • 【Java EE】----SpringBoot的日志文件
  • 【网络安全】2024年暗网威胁分析及发展预测
  • SpringMVC-组件解析
  • ubuntu22.04@laptop OpenCV Get Started: 002_reading_writing_videos
  • Elasticsearch(ES) 简述请求操作索引下文档 增删查改操作
  • Chrome扩展开发纪要
  • LeetCode-第28题-找出字符串中第一个匹配项的下标
  • 分享90个行业PPT,总有一款适合您
  • 【原创 附源码】Flutter海外登录--Tiktok登录最详细流程
  • 国内chatGPT3.5升级到chatGPT4.0的教程(24年2月更新)
  • 【python量化交易】qteasy使用教程01 - 安装方法及初始化配置
  • UML 2.5图形库
  • 分享springboot框架的一个开源的本地开发部署教程(若依开源项目开发部署过程分享持续更新二开宝藏项目PostgresSQL数据库版)
  • 打卡今天学习 Linux
  • 单片机精进之路-3流水灯