使用 goroutine 进行迭代会产生意想不到的结果
Iterating using a goroutine is giving unexpected result
我在 goroutine 中根据迭代变量 i
进行了一些条件检查,发现它给出了我没有预料到的结果,我决定用一些简单的代码来确认它。
for i := 1; i <= 5; i++ {
wg.Add(1)
fmt.Println(i)
go func() {
fmt.Println(i)
wg.Done()
}()
}
wg.Wait()
1
2
3
4
5
6
6
6
6
6
这是预期的行为吗?有人可以解释为什么 6 被打印了 5 次,尽管我只迭代到 5 次吗??
你的所有 goroutines 运行 异步在你的 for 循环完成后。
在你的 for 循环结束时 i
等于 6,因此,你的 goroutines 每个记录数字 6。
要解决这个问题,您可以创建一个闭包,并将 i
的当前值保存在其中,以便当 goroutine 运行时,它会以正确的 i
值运行。
要做到这一点,只需更改您的代码,使其看起来像
go func(x int) {
fmt.Println(x)
wg.Done()
}(i) // <--- "save" value of i at this point in time.
这样你 "save" 函数内部 i
的值你告诉 goroutine 执行这样稍后,当 for 循环有 运行 完成时,它不会不要使用 i
的 当前 值,即 6;相反,它使用创建 goroutine 时 i
的 old 值。
我在 goroutine 中根据迭代变量 i
进行了一些条件检查,发现它给出了我没有预料到的结果,我决定用一些简单的代码来确认它。
for i := 1; i <= 5; i++ {
wg.Add(1)
fmt.Println(i)
go func() {
fmt.Println(i)
wg.Done()
}()
}
wg.Wait()
1
2
3
4
5
6
6
6
6
6
这是预期的行为吗?有人可以解释为什么 6 被打印了 5 次,尽管我只迭代到 5 次吗??
你的所有 goroutines 运行 异步在你的 for 循环完成后。
在你的 for 循环结束时 i
等于 6,因此,你的 goroutines 每个记录数字 6。
要解决这个问题,您可以创建一个闭包,并将 i
的当前值保存在其中,以便当 goroutine 运行时,它会以正确的 i
值运行。
要做到这一点,只需更改您的代码,使其看起来像
go func(x int) {
fmt.Println(x)
wg.Done()
}(i) // <--- "save" value of i at this point in time.
这样你 "save" 函数内部 i
的值你告诉 goroutine 执行这样稍后,当 for 循环有 运行 完成时,它不会不要使用 i
的 当前 值,即 6;相反,它使用创建 goroutine 时 i
的 old 值。