我有以下代码:
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()
在dirs中,我有[“one”,“two”],如果我看到以下内容:
le dir one
le dir two
working on one
working on one
为什么gorouting没有使用dir
的正确值?
答案 0 :(得分:1)
您正在创建多个执行线程(goroutines),这些线程无法保证以任何特定顺序执行(这是并发的本质)。因此,理论上主线程可以在调度程序调度任何goroutine之前完成其循环。这可能就是你所经历的。
因为主循环在任何goroutine执行第一条指令之前已经完成执行,dir
已经到达其最终值,所以每个goroutine都会使用它(不值在创建闭包时dir
。)
如果你循环次数更多(dirs
中的元素更多)或者每次循环迭代需要花费更长的时间来执行(例如,如果你在循环中Wait()
),你可能会开始看看你的主程序的印刷语句和你的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
}