Go语言使用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 (i)
go func () {
println(i)
wg.Done()
}()
}
wg.Wait()
}
运行结果:
9
9
9
9
9
9
9
9
9
9
- for range 下的迭代变量 i 的值是共用的。
- main 函数所在的 goroutine 和后续启动的 goroutines 存在竞争关系。
使用
go run -race 来看一下数据竞争情况:
#CGO ENABLED=l go run - race src/c7_2_la.go
WARNING: DATA RACE
Read at 0x00c4200140b8 by goroutine 13:
main.main.funcl()
/project/go/src/gitbook/gobook/chapter7/src/c7_2_la.go:14 +0x38
Previous write at 0x00c4200140b8 by main goroutine:
main.main ()
/project/go/src/gitbook/gobook/chapter7/src/c7_2_la.go:11 +0xdf
Goroutine 13 (running) created at:
main.main ()
/project/go/src/gitbook/gobook/chapter7/src/c7_2_la.go:l3 +0xl35
=================
9
9
9
9
9
9
9
9
9
9
Found 1 data race(s)
exit status 66
正确的写法是使用函数参数做一次数据复制,而不是闭包。示例如下:
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(i)
//这里有一个实参到形参的值拷贝
go func(a int) {
println(a)
wg.Done()
}(i)
}
wg.Wait ()
}
运行结果:
9
0
1
2
3
4
5
6
7
8
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算