我有以下代码:
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/