两个例子
package main
import (
"fmt"
"time"
)
func Process1(tasks []string) {
for _, task := range tasks {
// 启动协程并发处理任务
go func() {
fmt.Printf("Worker start process task: %s\n", task)
}()
}
}
func main() {
tasks := []string{"1", "2", "3", "4", "5"}
Process1(tasks)
time.Sleep(2 * time.Second)
}
结果:
第一次运行
Worker start process task: 3
Worker start process task: 4
Worker start process task: 4
Worker start process task: 5
Worker start process task: 5
第二次运行
Worker start process task: 2
Worker start process task: 5
Worker start process task: 5
Worker start process task: 5
Worker start process task: 5
package main
import (
"fmt"
"time"
)
func Process1(tasks []string) {
for _, task := range tasks {
// 启动协程并发处理任务
go func() {
fmt.Printf("Worker start process task: %s\n", task)
}()
}
}
func Process2(tasks []string) {
for _, task := range tasks {
// 启动协程并发处理任务
go func(t string) {
fmt.Printf("Worker start process task: %s\n", t)
}(task)
}
}
func main() {
tasks := []string{"1", "2", "3", "4", "5"}
Process2(tasks)
time.Sleep(2 * time.Second)
}
结果
第一次运行
Worker start process task: 5
Worker start process task: 4
Worker start process task: 2
Worker start process task: 3
Worker start process task: 1
第二次运行
Worker start process task: 2
Worker start process task: 5
Worker start process task: 4
Worker start process task: 1
Worker start process task: 3
for index, value := range xxxindexvalue
循环变量是易变的
首先,循环变量实际上只是一个普通的变量。
for index, value := range xxx
如果循环体中会启动协程(并且协程会使用循环变量),就需要格外注意了,因为很可能循环结束后协程才开始执行,
此时,所有协程使用的循环变量有可能已被改写。(是否会改写取决于引用循环变量的方式)
循环变量需要绑定
tasktask
tasktask
ps:
简单点来说
- 如果循环体没有并发出现,则引用循环变量一般不会出现问题;
- 如果循环体有并发,则根据引用循环变量的位置不同而有所区别
- 通过参数完成绑定,则一般没有问题;
- 函数体中引用,则需要显式地绑定
参照 topgoer的文章。