【发布时间】:2019-08-08 09:08:39
【问题描述】:
似乎无法弄清楚为什么我会收到错误消息:致命错误:所有 goroutines 都处于睡眠状态 - 死锁!。
我怀疑我下面的块中发生了竞争条件,该条件只能在通道关闭后执行。
我认为添加一个同步 WaitGroup 会有所帮助,但它只是给了我这个死锁。我看到的和我在网上看到的样本很接近,所以我不确定这里有什么问题。
func S3UploadFolder(instance *confighelper.Instance, sess *session.Session,
srcFolder string, bucketName string) (err error) {
log.Println("S3UploadFolder", srcFolder, bucketName)
wg := &sync.WaitGroup{}
// find files recursively
walker := make(fileWalk)
wg.Add(1)
go func() {
// Gather the files to upload by walking the path recursively
if err := filepath.Walk(srcFolder, walker.Walk); err != nil {
log.Fatalln("Walk failed:", err)
}
wg.Done()
close(walker)
}()
wg.Wait()
for path := range walker {
// THE GO routine above needs to have finished by the time this for loop
// ranges over the channel
fmt.Println(path)
}
return
}
type fileWalk chan string
func (f fileWalk) Walk(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
f <- path
}
return nil
}
【问题讨论】:
-
主 goroutine 在调用 wg.Wait() 之前没有在通道上接收。 walker goroutine 阻塞发送到通道,因为没有接收器。您没有显示所有相关代码,但修复可能是删除与等待组相关的所有代码。
-
抱歉,是的,
部分包含通道上的范围。我将更新我的问题以包含此代码。我试图等到 go 例程完成后再继续块 -
为什么 walker goroutine 需要在遍历通道的循环之前完成?
-
我正在解决一些文件未包含在 for 范围内的缺陷。我怀疑在遇到 for range 语句时 go 线程仍在查找文件的竞争条件。我的想法是此时通道尚未完成,因此测距将只是在 walker 中找到的总文件的一个子集。这就是我设置同步等待的原因。
-
在通道关闭之前,通道上的范围不会完成。 walker goroutine 在 walk 完成之前不会关闭通道。通道操作不会丢失文件名。
标签: go