先看这个代码有问题吗?

文章目录
- 先看这个代码有问题吗?
- 问题
- 正确的是
- 如果不传递 i 给 goroutine,还会出现什么问题 ?
问题
- 在循环中启动了 goroutine (go func() {…}),但没有等待这些 goroutine 完成
- 主函数可能在所有 goroutine 执行前就结束了
- 循环变量 i 被所有 goroutine 共享,可能导致输出结果不符合预期
正确的是
package main
import (
"fmt"
"sync"
)
func main() {
testRange2()
}
func testRange2() {
arr := make([]int, 10)
var wg sync.WaitGroup
for i := range arr {
wg.Add(1)
go func(val int) {
defer wg.Done()
fmt.Println(val)
}(i) // 将 i 作为参数传递给 goroutine
}
wg.Wait() // 等待所有 goroutine 完成
}如果不传递 i 给 goroutine,还会出现什么问题 ?
如果不将循环变量 i 作为参数传递给 goroutine,会出现一个常见且容易被忽视的问题:所有 goroutine 可能会打印出相同的值,通常是数组的最后一个索引值(在这个例子中是 9)。
这个问题的原因是:
- 闭包变量捕获机制:Go 中的闭包会捕获外部变量的引用,而不是值的副本。
- 循环变量共享:所有 goroutine 共享同一个循环变量 i 的引用。
- 执行时机:goroutine 的实际执行可能会延迟到循环结束后才开始。
循环结束时的变量状态:当循环结束时,i 的值已经变成了 10(超出了数组范围),或者在 range 循环的情况下是 9(最后一个索引)。
















