go - 循环中的 Println 和闭包输出不同的值

标签 go

我有以下代码:

dirs, err      := get_directories(bucket, start_dir, "")

其中 dirs 是一个字符串数组。之后,我循环遍历它们:

for _, dir     := range dirs {
  fmt.Println("le dir",dir)
  go func() {
    fmt.Println("working on",dir)
    get_files(bucket, dir, "")
    wg.Done()
  }()
}

wg.Wait()

在目录中,我有["one", "two"],如果我看到以下内容:

le dir one
le dir two
working on one
working on one

为什么 gorouting 没有使用正确的 dir 值?

最佳答案

您正在创建多个执行线程(goroutine),它们不能保证以任何特定顺序执行(这是并发的本质)。因此,理论上主线程可以在调度程序调度任何 goroutine 之前完成其循环。这可能就是您正在经历的。

因为在任何 goroutines 执行它的第一条指令之前主循环已经完成执行,dir 已经到达它的最终值,所以每个 goroutine 将使用那个(不是 创建闭包时 dir 的值)。

如果你循环了更多次(dirs 中有更多元素)或者如果每个循环迭代花费了更长的时间来执行(例如,如果你 Wait()ed in你的循环),你可能会开始看到你的主例程和你的 goroutines 的打印语句之间有一些混合。

这是对您的示例的简化的、惯用的重写,供其他可能发现此问题有用的人使用:

http://play.golang.org/p/6G_8xOi9Fi

package main

import "fmt"

func main() {
    ch1 := make(chan bool)

    // with 1000 iterations, you can probably see some intermingling
    // between lines printed via goroutines and those of your main thread
    for i:=0;i<1000;i++ {
        fmt.Println("before kicking off goroutine:", i)
        go func() {
            fmt.Println("in goroutine:", i)
            ch1 <- true // signal 'done'
        }()
        // alternatively, add a `time.Wait()` here
        // (and reduce the loop iterations) to see
        // intermingling for a different reason.
    }

    <- ch1 // wait for goroutines to complete
}

关于go - 循环中的 Println 和闭包输出不同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20961302/

相关文章:

go - gouuid 在 V5 上会始终生成相同的值吗

sorting - 如何按 map 的值对 slice 进行排序

go - 将通用结构保存到 redis

php - 相当于 PHP 的 'implode'

post - 如何在 revel golang 中获取 POST 参数

go - 分类链接不区分大小写

go - 在 Go 模板范围循环中,是否在每次迭代时重置循环外声明的变量?

dictionary - map[string][]string 和 map[string]string 有什么区别?

go - Go 中的高级函数

Go:读取 zip 文件中的行 block