Go十大常见错误第10篇(Goroutine和循环变量一起使用的坑)
前言
这是Go十大常见错误系列的第10篇:Goroutine和循环变量一起使用的坑。素材来源于Go布道者,现Docker公司资深工程师Teiva Harsanyi。
本文涉及的源代码全部开源在:Go十大常见错误源代码,欢迎大家关注公众号,及时获取本系列最新更新。
常见错误
对于Go初学者,很容易犯的一个错误就是goroutine和循环变量结合在一起使用时,错误地使用了循环变量。
【Go十大常见错误第10篇(Goroutine和循环变量一起使用的坑)】比如下面这个例子:
ints := []int{1, 2, 3}
for _, i := range ints {
go func() {
fmt.Printf("%v\n", i)
}()
}
这段程序的输出结果应该是什么?
Go初学者可能认为输出结果应该是
1 2 3
,但实际情况并不是。这个例子里,3个goroutine共享同一个变量
i
,最后输出的结果大概率是输出3 3 3
。要解决这个问题,主要有2个解决方案。
解决方案1
把循环变量
i
作为goroutine函数的一个参数,编译器在执行go func(i int)
时,就会解析到i
的值,确保每个goroutine可以拿到自己想要的值。ints := []int{1, 2, 3}
for _, i := range ints {
go func(i int) {
fmt.Printf("%v\n", i)
}(i)
}
解决方案2
创建一个新的变量,用于goroutine。
ints := []int{1, 2, 3}
for _, i := range ints {
i := i
go func() {
fmt.Printf("%v\n", i)
}()
}
推荐阅读
- Go十大常见错误第1篇:未知枚举值
- Go十大常见错误第2篇:benchmark性能测试的坑
- Go十大常见错误第3篇:go指针的性能问题和内存逃逸
- Go十大常见错误第4篇:break操作的注意事项
- Go十大常见错误第5篇:Go语言Error管理
- Go十大常见错误第6篇:slice初始化常犯的错误
- Go十大常见错误第7篇:不使用-race选项做并发竞争检测
- Go十大常见错误第8篇:并发编程中Context使用常见错误
- Go面试题系列,看看你会几题?
公众号:coding进阶。关注公众号可以获取最新Go面试题和技术栈。
个人网站:Jincheng's Blog。
知乎:无忌。
福利 我为大家整理了一份后端开发学习资料礼包,包含编程语言入门到进阶知识(Go、C++、Python)、后端开发技术栈、面试题等。
关注公众号「coding进阶」,发送消息 backend 领取资料礼包,这份资料会不定期更新,加入我觉得有价值的资料。还可以发送消息「进群」,和同行一起交流学习,答疑解惑。
References
- https://itnext.io/the-top-10-...
推荐阅读
- 错误的婚姻是会死人的
- iOS|iOS kCFErrorDomainCFNetwork Code=303 错误解决方案
- #|【安卓学习之常见问题】初始化Spinner、CheckBox和SeekBar不触发事件
- 中间件|【Redis】Redis 常见面试问题
- 汽车出行|百人会张永伟:全球汽车供应链变革十大特点
- Bash|Bash 脚本中的错误处理
- 常见设计模式
- 渗透测试|渗透测试-Web常见漏洞描述及修复建议
- 妞子老师(在微信上卖东西,哪些最基本的错误你一定不要犯(——头像篇))
- 对 Go2 错误处理提案的批判