新手问题 goroutine 语法问题

Goho · 2019年01月21日 · 最后由 chengjingtao 回复于 2019年01月22日 · 580 次阅读
package main
    import (
    "fmt"
    "time"
)

func main() {
    for i:=1;i<10;i++ {
    go func(i int) {
    fmt.Println(i)
    }(i)
}
//暂停一会,保证打印全部结束
time.Sleep(1e9)
}

请问第11行的(i) 什么含义
更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio

建议你调整下格式内容,发完帖子看一下,你这样哪里看得出来第 11 行在哪里?

比如定义一个 func test(i int), 我现在去 main 去调用 test func, 调用的时候是这样 test(a), 这里的 a 就代表你的 i, 也就是传参数

i 是传给匿名协程的参数

i 正如楼上所说传给匿名函数具体的值

这个 不是 goroutine 的语法。为了解决闭包中参数的问题,使用了传参的方式来调用方法。
实际你的问题应该是这样

package main
    import (
    "fmt"
    "time"
)

func main() {
    for i:=1;i<10;i++ {
    go func() {
    fmt.Println(i)
    }()
}
//暂停一会,保证打印全部结束
time.Sleep(1e9)
}

为什么打印的结果在绝大部分情况下都是 10 ? 为什么 使用 go func(i int) { } (i) 可以避免这个问题?
有两点你需要注意

  1. go func(){}() 只是会将 func 加入到 goroutine 的执行队列, 并不是真正启动 goroutine。在大部分情况下,上述逻辑,会等到 最后的 time.Sleep 时,才会有机会启动 goroutine。而且先启动那个 也是不确定的。
  2. 启动 goroutine 时,对于我写的这个例子, func 里边引入 一个变量 i, 等到执行的时候, 这个变量 i 的值 已经是最后的 10
    所以 最终 打印的都是 10 (绝大部分情况下)。

改成 func(i int){}(i) 这种形式,在将 goroutine 加入队列时, 这个 func 的形参 i 的值 是已经确定的。就是加入时的值。 执行 func 的时候,只需要从这个形参取值即可。 所以 能 避免 上述的问题。

在大部分语言里边的闭包里边, 都有类似的问题。而且解决方案也是一致的。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册