关于GO闭包的东西,我有点忘了,是不是有参数就马上串行执行?没参数就是并行异步执行?
并不是这样的。参数的存在与否并不决定它是同步还是异步执行。
在 Go 语言中,执行方式(串行还是异步)仅取决于你如何调用它:
- 串行执行(同步):直接调用函数或匿名函数。
- 异步执行(并行/并发):使用
go关键字启动协程(Goroutine)。
你产生这种"模糊印象"的原因,很可能是因为在循环中使用 Goroutine 时,为了避免闭包捕获外部变量导致的作用域陷阱,通常会有两种写法:
1. 传参数的写法(推荐)
如果你通过参数传递变量,每个协程都会拿到该变量在当前时刻的副本。
for i := 0; i < 5; i++ {
go func(n int) {
fmt.Println(n) // 这里会正确输出 0, 1, 2, 3, 4 (顺序随机)
}(i) // 立即将当前的 i 作为参数传入
}
2. 不传参数的写法(容易出错)
如果不传参数,闭包会直接引用外部变量 i。因为协程启动需要时间,等协程真正开始运行的时候,循环可能已经跑完了,此时 i 的值可能已经是 5。
for i := 0; i < 5; i++ {
go func() {
fmt.Println(i) // 可能全部输出 5
}()
}
总结
- 传参:是为了"固定"变量值,防止多个协程引用同一个一直在变的变量。
- 不传参:闭包会引用外部作用域变量的地址。
- 是否异步:只看有没有那个
go关键字。