乐趣区

关于go:Go十大常见错误第10篇Goroutine和循环变量一起使用的坑

前言

这是 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-…
退出移动版