前言
这是Go十大常见谬误系列的第10篇:Goroutine和循环变量一起应用的坑。素材来源于Go布道者,现Docker公司资深工程师Teiva Harsanyi。
本文波及的源代码全副开源在:Go十大常见谬误源代码,欢送大家关注公众号,及时获取本系列最新更新。
常见谬误
对于Go初学者,很容易犯的一个谬误就是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面试题系列,看看你会几题?
开源地址
文章和示例代码开源在GitHub: Go语言高级、中级和高级教程。
公众号:coding进阶。关注公众号能够获取最新Go面试题和技术栈。
集体网站:Jincheng's Blog。
知乎:无忌。
福利
我为大家整顿了一份后端开发学习材料礼包,蕴含编程语言入门到进阶常识(Go、C++、Python)、后端开发技术栈、面试题等。
关注公众号「coding进阶」,发送音讯 backend 支付材料礼包,这份材料会不定期更新,退出我感觉有价值的材料。还能够发送音讯「进群」,和同行一起交流学习,答疑解惑。
References
- https://itnext.io/the-top-10-...