【golang】匿名内部协程,值传递与参数传递

代码例子

下面代码的区别是直接调用循环变量,这里使用的就是这个变量的引用,而不是将参数的副本传递给协程执行

go 复制代码
for task := range taskChan {
    wg.Add(1)
    go func() {
        defer wg.Done()
        task.Do()  // 使用外部循环变量
    }()
}
go 复制代码
func DistributeTasks(taskChan <-chan *AddTask, resChan chan int) {
	var wg sync.WaitGroup
	for task := range taskChan {
		wg.Add(1)
		go func(t *AddTask) {
			defer wg.Done()
			t.Do()
		}(task) // 注意要当作参数传入,而不是直接在 开启的协程 内部调用task,
	}
	wg.Wait()
	close(resChan)
}

结论

  • 可能导致的问题:
    • 在 Go 语言中,当你使用 go 关键字启动一个 goroutine 时,它会在一个新的并发执行单元中运行。在原始代码中,将 task 作为参数传递给匿名函数,确保了每个 goroutine 操作的 task 是独立的,因为函数参数是按值传递的,这意味着在 go 语句执行时,会将 task 的副本传递给匿名函数。
    • 如果不将 task 作为参数传递,而是直接在匿名协程 goroutine 中调用 task,由于 goroutine 可能会在 for 循环的下一次迭代开始后才开始执行,而 for 循环会不断更新 task 的值,这可能会导致 goroutine 看到的 task 值不是你期望的那个。
    • 例如:goroutine执行时间很长,而程序中开启goroutine是一个很快的过程,开启完毕之后就执行下一次for循环了,循环变量task也就变了,之前开启的goroutine执行到task.Do() 的时候,已经是其他次循环的task变量
go 复制代码
for task := range taskChan {
    wg.Add(1)
    go func() {
        defer wg.Done()
        //假如这里有比较久的耗时操作
        task.Do()  // 使用外部循环变量,这时候可能已经当时那一次循环的task了,因为开启协程这段代码一下子就执行完毕
    }()
}
相关推荐
数据狐(Datafox)7 分钟前
1688商品列表API接口解析(附 JSON 样例)
java·开发语言·数据库·爬虫·json
EatFan19 分钟前
一个二维码背后的系统设计:批次生成、绑定、扫码与数据统计怎么做?
java·后端·微信小程序·二维码·qrcode
石小石Orz24 分钟前
民间AI排行榜单新鲜出炉,Fable 5.1仅排第三
前端·后端·ai编程
小灰灰搞电子38 分钟前
Rust Once 、OnceLock、LazyLock 一次性初始化详解
开发语言·后端·rust
hqyjzsb1 小时前
规划工商管理大学成长:搭建四层能力体系,重视高阶的 AI 能力建设
开发语言·人工智能·python·microsoft·职场和发展·数据挖掘·业界资讯
我不会起名字3221 小时前
一天一道算法题(35):电话号码的字母组合
java·数据结构·后端·python·leetcode·go·回溯
for_ever_love__1 小时前
爬虫项目: 获取高分电影的数据总结
开发语言·python·学习
weixin_307779131 小时前
C++代码实现MATLAB中的ode23t函数功能
开发语言·c++·算法·matlab
星栈1 小时前
ADK-Rust 是什么?Rust 生态新一代 AI Agent 开发套件
后端·agent
君顾12 小时前
24小时自助健身房系统开发实战与完整指南
java·开发语言·健身房