小白求助 怎么都想不明白这个运行结果是怎么得到的

a1al · · 1285 次点击
```go package main import ( "fmt" "sync" ) func main() { doOnve() } func doOnve() { var once sync.Once funBody := func() { //被检测的是否只执行1次的函数对象 fmt.Println("Only once") } c := make(chan int) //无缓冲channel for i:=0;i<10;i++{ go func(i int) { //10个协程 once.Do(funBody) c <- i }(i) } for i := 0; i < 10; i++ { fmt.Println( <- c) } } ``` 麻烦删下楼,没刷新页面,回晚了
#4
更多评论
1、for 循环中的临时变量使用的为相同的一个地址空间、因此for循环完毕时临时变量的值已改变、导致协程中传递到通道的值也会不符合预期。 2、在for循环中起协程使用临时变量需要再次将临时变量的值拷贝一份及赋值到新的变量空间。 3、去除once的执行、会看到会有不同的数字输出、因为for循环和协程是异步的、又因为1的原因、所以值不确定。 4、加上once的执行,每次协程都会先once判断一次才将数据传递到通道,for循环已遍历完毕,因此临时变量的值为最后一值。 5、for循环临时变量会在执行加1操作后,在判断条件、因此临时变量值为10。
#1
老哥 我懂了 我忽略了闭包是同地址的参数 改成下面这样完美解决 ```go for i:=0;i<10;i++{ go func(x int) { once.Do(funBody) //c <- i //若是这样写 输出结果会是 10 10 10...10 因为 闭包参数是外面的10 ;正确方法是为该匿名函数设置参数 并按参数输出 c <- x }(i) } ``` ![image.png](https://static.studygolang.com/211028/d7d4fc854aec5b3415454f14d2b53093.png)
#2