Go——range复用临时变量

2023-05-16

range复用临时变量

package main

import "sync"

func main() {
	wg := sync.WaitGroup{}

	si := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

	for i := range si {
		wg.Add(1)
		go func() {
			println(i)
			wg.Done()
		}()
	}
	wg.Wait()
}

//结果
9
9
9
9
9
9
9
9
9
9

程序结果并没有如我们预期一样遍历切片,而是全部打印9,有两点原因导致这个问题:

  1. for range下的迭代变量i的值是共用的。
  2. main函数所在的goroutine和后续启动的goroutines存在竞争关系。

使用go run-race来看一下数据竞争情况:

==================
WARNING: DATA RACE
Read at 0x00c42007e010 by goroutine 5:
  main.main.func1()
      /Users/acton_zhang/go/gobook/src/pro7_2/demo1/main.go:13 +0x3b

Previous write at 0x00c42007e010 by main goroutine:
  main.main()
      /Users/acton_zhang/go/gobook/src/pro7_2/demo1/main.go:10 +0xe8

Goroutine 5 (running) created at:
  main.main()
      /Users/acton_zhang/go/gobook/src/pro7_2/demo1/main.go:12 +0x13e
==================
1
2
3
4
5
6
7
8
9
9
Found 1 data race(s)
exit status 66

可以看到Goroutine 5和main goroutine存在数据竞争,更进一步证实了range共享临时变量。range在迭代写的过程中,多个goroutine并发地去读。

正确的写法是使用函数参数做一次数据复制,而不是闭包。示例如下:

package main

import "sync"

func main() {
	wg := sync.WaitGroup{}

	si := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

	for i := range si {
		wg.Add(1)
		//这里有一个实参到形参的值拷贝
		go func(a int) {
			println(a)
			wg.Done()
		}(i)
	}
	wg.Wait()
}

//结果
1
0
3
2
6
4
5
7
8
9

可以看到新程序的运行结果符合预期。这个不能说是缺陷,而是Go语言设计者为了性能而选择的一种设计方案,因为大多情况下for循环块里的代码是在同一个goroutine里运行的,为了避免空间的浪费和GC的压力,复用了range迭代临时变量。语言使用者明白这个规约,在for循环下调用并发时要复制迭代变量后再使用,不要直接引用for迭代变量。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Go——range复用临时变量 的相关文章

  • idea永久激活使用

    原文 xff1a https www cnblogs com dfsu p 11362594 html 先感谢大佬一波 xff0c 亲测可用 xff0c 小伙伴们按照博客上面操作就行 声明 支持知识产权 xff0c 支持正版产权 xff0c
  • 电信企业文化

    1 2017年 xff0c 中国电信资产规模超过 xff08 A xff09 亿元人民币 xff0c 年收入规模超过4100亿元人民币 A 8000 B 8500 C 9000 D 9500 2 中国电信以党的建设统领企业发展全局 xff0
  • easyui datagrid的行编辑器editor 如何实现新增时可修改,编辑时,不可修改

    项目出现一个需求 xff0c 要求用户界面的用户名 xff0c 新增时 xff0c 可自由输入 xff0c 编辑时 xff0c 不可修改 html页面 lt table id 61 34 gridlist 34 data bind 61 3
  • easyui datagrid的editor编辑器如何为validatebox控件添加改变事件

    项目中需要为行编辑器Editor的某个列的文本框添加改变事件 需求 xff1a 新增行时 xff0c 为用户名输入特殊字符进行验证 xff0c 不允许保存用户数据 html页面 lt table id 61 34 gridlist 34 d
  • 中标麒麟系统远程桌面连接

    中标麒麟是中国自主研发的操作系统 逃 搭载了龙芯 xff08 mips xff09 的中标麒麟OS使用起来非常流畅 xff08 逃 远程连接需要的两个软件 Xmanager amp Xshell 使用起来还是可以的 首先要在麒麟系统上开启s
  • ubuntu 环境变量修改和恢复总结

    通常设置环境变量有三种方法 xff1a 一 临时设置 export JAVA HOME 61 usr lib jvm java 1 7 0 openjdk amd64 export PATH 61 JAVA HOME PATH 二 当前用户
  • Go——反射规则

    反射规则 Value Type和类型实例之间的相互转化如下图 xff1a 1 反射API 从实例到Value 通过实例获取Value对象 xff0c 直接使用reflect ValueOf 函数 例如 xff1a span class to
  • 转载 matlab矩阵数组常用操作

    一 length 返回矩阵最长维的的长度 ndims 返回维数 numel 返回矩阵元素个数 size 返回每一维的长度 xff0c rows cols 61 size A 矩阵块操作 1 repmat 数组块状复制 2 blkdiag 对
  • 微微一笑很倾城(2)

    微微一笑很倾城 正文 第30章 组队前 xff0c 雷神妮妮想死 组队后 xff0c 看到队伍里那一排ID xff0c 雷神妮妮瞬间回光返照HP全满了 就像老话说的那样 xff0c 一个妮妮被雷劈了 xff0c 千万个妮妮在电闪雷鸣中站起来
  • Get the Job You Want(大学英语综合教程4课文)

    UNIT3 1 Harvey Mackay who runs his own company often interviews applicants for jobs Here he lets us into the secret of w
  • Debian9.5 VNC Server远程桌面配置

    VNC概述 VNC Virtual Network Console 是虚拟网络控制台的缩写 VNC 是一款优秀的远程控制工具软件 xff0c 由著名的 AT amp T 的欧洲研究实验室开发的 VNC 是在基于 UNIX 和 Linux操作
  • 嵌入式常用的英文缩写词汇

    原文地址 xff1a https wenku baidu com view 9d4051f4700abb68a982fb4e html 嵌入式常见英文缩写和英文词汇 搜集中 英文缩写 ARM xff1a Advanced RISC Mach
  • 先安装VS2017再安装VS2015遇到的CMake问题

    先安装了VS2017 xff0c 后来有需求安装VS2015 xff0c 安装VS2015的时候遇到下图问题 xff0c 但是控制面板里面看不到Microsoft Visual C 43 43 2015 Redistributable的项目
  • 粒子群算法优化BP生物能神经网络

    定义 xff1a 粒子群中每个粒子的位置表示BP神经网络当前迭代中权值的集合 xff0c 每个粒子的维数由网络中起连接作用的权值的数量和阈值个数决定 xff0c 以给定训练样本集的神经网络输出误差作为神经网络训练问题的适应度函数 xff0c
  • 实现分布式锁技术:Redisson

    1 需求 Spring分布式项目涉及到定时任务 xff0c 目前解决方案 xff1a xff08 1 xff09 集成quartz xff1b xff08 2 xff09 集成redisson xff0c 由于集成quartz需要涉及到数据
  • nginx支持websocket及websocket部分原理介绍

    nginx支持websocket及websocket部分原理介绍 最近ipc通过websocket与server进行通行 xff0c 经过无法通过nginx进行反向代理 xff0c 只有直连nodejs端口 而且部署到阿里云用了slb之后同
  • Windows下分布式环境搭建以及简单测试

    环境配置 xff1a 解压文件 xff1a Nginx服务器和Tomcat服务器 Tomcat服务器配置 xff1a xff08 conf server xml xff09 Nginx配置 xff1a xff08 conf nginx co
  • Go——Inject库

    1 依赖注入和控制反转 在介绍inject之前先简单介绍 依赖注入 和 控制反转 的概念 正常情况下 xff0c 对函数或方法的调用是调用方的主动直接行为 xff0c 调用方清楚地知道被调的函数名是什么 xff0c 参数有哪些类型 xff0
  • 浅谈SpringBoot核心注解原理

    SpringBoot核心注解原理 今天跟大家来探讨下SpringBoot的核心注解 64 SpringBootApplication以及run方法 xff0c 理解下springBoot为什么不需要XML xff0c 达到零配置 首先我们先
  • Quartus II和Modelsim的联合仿真(详细)

    这篇文章不需要在modelsim中建库 映射 建工程等一些繁琐的步骤 xff0c 直接使用modelsim中的默认work库 使用quartus 43 modelsim联合仿真 首先推荐一篇文章 http www cnblogs com e

随机推荐

  • requests.post处理Content-Type: multipart/form-data的请求

    前几天遇到一个需求 xff0c 要调用一个接口发送请求 xff0c 抓包之后得到的数据是这样的 上网看了一些资料得知 xff0c 原来这个接口的数据是通过multipart form data格式传过去的 xff0c multipart f
  • 上一步,下一步(撤销和恢复)

    var data 61 data count 61 0 data list 61 function regain function handleSaveCss 获取workspace body里面的内容 var c 61 34 worksp
  • Ubuntu下dpkg安装软件遇到包依赖问题的处理方法

    造冰箱的大熊猫 64 cnblogs 2019 9 10 向灵魂工程师致敬 xff01 在Ubuntu环境下通过dpkg命令安装deb包时 xff0c 如果遇到包依赖问题 xff0c 如 sudo dpkg i xxx deb Readin
  • Ubuntu18优化桌面版的运行速度

    一 刚开始使用Ubuntu18后 xff0c 感觉开机和运行速度都不理想 xff0c 通过改变一些配置可以提高下用户体验感 二 改变一些配置 a 使用Preload预加载 sudo apt install preload y b 禁用不必要
  • Debian安装mplayer,解决没有声音及声卡独占问题

    通过软件中心可以安装Gnome mplayer 本来以为这样这个播放器已经是 万能 的了 xff0c 但是最近下载了几个 mkv的电影 却发现Gnome mplayer没有办法打开 感觉很失望 在网上找了一番后 说只要下载源代码自己安装就行
  • CentOS7中安装MySQL5.7

    安装必要的组件 yum install y autoconf automake imake libxml2 devel expat devel cmake gcc gcc c 43 43 libaio libaio devel bzr bi
  • 20190708新的开始

    题目描述 发展采矿业当然首先得有矿井 xff0c 小 FF 花了上次探险获得的千分之一的财富请人在岛上挖了 n 口矿井 xff0c 但他似乎忘记考虑的矿井供电问题 为了保证电力的供应 xff0c 小 FF 想到了两种办法 xff1a 在这一
  • Debian安装JDK

    sudo tar zxvf jdk 8u60 linux x64 tar gz C usr local vi bashrc export JAVA HOME 61 usr local jdk1 8 0 60 export JRE HOME
  • Go——多值赋值和短变量声明

    1 多值赋值 可以一次性声明多个变量 xff0c 并可以在声明时赋值 xff0c 而且可以省略类型 xff0c 但必须遵守一定的规则要求 xff0c 具体看下面的示例 如下都是合法的 span class token comment 相同类
  • 「一本通 1.2 练习 2」扩散(loj10015)

    题目描述 一个点每过一个单位时间就会向 4 个方向扩散一个距离 xff0c 如图所示 xff1a 两个点 a b 连通 xff0c 记作 e a b xff0c 当且仅当 a b 的扩散区域有公共部分 连通块的定义是块内的任意两个点 u v
  • .db文件打开方式

    有时在工作中 xff0c 数据库格式db后缀的格式 xff0c 直接是打不开的 xff0c 所以我这里使用了数据库管理工具 xff0c 步骤如下 1 在电脑安装 Navicat Premium xff0c 安装后在桌面生成图标 xff0c
  • MathType的配置问题;将word中的公式转换为mathtype格式失败,缺少OMML2MML.XSL

    安装MathType后打开word报错 打开会出现以下问题 xff1a 首先 xff0c 把startup添加到word的信任中心 xff1a 要确保路径被office信任 依次打开word gt 文件 gt 选项 gt 信任中心 gt 信
  • XMPP系列(四)---发送和接收文字消息,获取历史消息功能

    今天开始做到最主要的功能发送和接收消息 获取本地历史数据 先上到目前为止的效果图 xff1a 首先是要在XMPPFramework h中引入数据存储模块 xff1a 聊天记录模块的导入 import 34 XMPPMessageArchiv
  • linux新增磁盘后,用fdisk等命令查询不到

    ls sys class scsi host xff08 会看到有host0 host1 hostN xff0c 对每个host进行如下操作 xff09 echo 34 34 gt sys class scsi host host0 sca
  • ubuntu上源码编译安装mysql5.7.27

    一 查看操作系统环境和目录结构 xff0c 并创建mysql用户和组 xff0c 以及规划安装mysql所需要的目录 cat etc issue 查看发行版本信息 xff1a cat proc version 查看正在运行的内核版本信息 u
  • (转-收集)MSSQL手工注入语句集合

    and exists select from sysobjects 判断是否是MSSQL and exists select from tableName 判断某表是否存在 tableName为表名 and 1 61 select 64 6
  • 滚动视图 UIScrollView

    UIScrollView xff1a 提供可以显 示 大于应 用窗 口的内容功能的控件 用户可以通过 手势使内容滚动和缩放 从 而查 看全部内容 初始化一个UIScrollView的对象 1 UIScrollView scroll 61 U
  • 基于steam的游戏销量预测 — PART 1 — 爬取steam游戏相关数据的爬虫

    语言 xff1a python 环境 xff1a ubuntu 爬取内容 xff1a steam游戏标签 xff0c 评论 xff0c 以及在 steamspy 爬取对应游戏的销量 使用相关 xff1a urllib xff0c lxml
  • WechatHelper

    using System using System Collections Generic using System Configuration using System IO using System Linq using System
  • Go——range复用临时变量

    range复用临时变量 span class token keyword package span main span class token keyword import span span class token string 34 s