goroutine 语法问题

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) 什么含义?
已邀请:

chengjingtao

赞同来自: whutchao dncmn Goho

这个 不是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的时候,只需要从这个形参取值即可。 所以 能 避免 上述的问题。

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

whutchao

赞同来自: Goho

i 是传给匿名协程的参数

EasyHacking - 微博/公众号 搜: EasyHacking

赞同来自:

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

TeiJin

赞同来自:

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

harrylee - 90后IT男

赞同来自:

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

要回复问题请先登录注册