concurrency - 在循环中执行函数闭包

标签 concurrency go closures

当执行下面的代码时,我得到了我在第一个循环完成时所期望的结果(从 0 到 9 的序列)。但是当第二个循环结束时,结果不是我所期望的(我期望与第一个循环相同的结果,但它只打印'10's):

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1)

        go func(j int) {
            defer wg.Done()

            fmt.Println(j)
        }(i)
    }

    wg.Wait()

    fmt.Println("done first")

    for i := 0; i < 10; i++ {
        wg.Add(1)

        go func() {
            defer wg.Done()

            fmt.Println(i)
        }()
    }

    wg.Wait()

    fmt.Println("done second")
}

输出:

0
1
2
3
4
5
6
7
8
9
done first
10
10
10
10
10
10
10
10
10
10
done second

为什么第二个循环不打印序列?

最佳答案

因为第一个每次都得到循环计数器的副本。而第二个获取作为闭包一部分捕获的变量。

首先,您在循环的每次迭代中将其传递到这里:

go func(j int) {
    defer wg.Done()

    fmt.Println(j)
}(i) // <------------ its passed in here as part of each loop iteration

第二个没有接收到任何东西.. 因此,循环计数器 i 被捕获为闭包的一部分。当第一个 go 例程执行时,for 循环已经完成。循环结束已将 i 变量(现在是闭包的一部分)设置为 10。Go routine #1 执行并打印 i 的值..已经有 10 个,其余的也一样。

TLDR:这里的问题是循环在任何 go 例程计划运行之前就完成了——就是这么快。因此,当 go 例程运行时,i == 10

关于concurrency - 在循环中执行函数闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24586141/

相关文章:

java - 具有消费者-生产者设计的 TCP 套接字服务器 'cpu time limit exceeded'

java - 如何在等待响应时不阻塞地实现请求-响应协议(protocol)?

networking - 如何知道 net.Listener 何时正确关闭?

lambdaj 闭包中使用的 Java 机制

c++ - 将闭包作为参数传递给构造函数 C++

java - 我们可以用Java实现协程类型的功能吗?

go - Flutter,在预构建的 GO .so 库上使用 DynamicLibrary.open(),无需编写 Native Code(Java/Swift)

go - 如何将JavaScript热重载与https集成到golang路由中以进行开发?

javascript - ajax回调函数可以看到父函数的变量吗?

java - 为什么以及何时使用 AtomicIntegerFieldUpdater?