此问题在此处已有答案:
Close multiple goroutine if an error occurs in one in go(3个答案)
Handle goroutine termination and error handling via error group?(1个答案)
25天前关闭。
我试图在循环中收集goroutine的错误,但不明白它必须如何正确工作https://go.dev/play/p/WrxE0vH6JSG
func init() {
rand.Seed(1500929006430687579)
}
func goroutine(n int, wg *sync.WaitGroup, ch chan error) {
defer wg.Done()
defer fmt.Println("defer done")
fmt.Println("num ", n)
if n == 1 {
ch <- fmt.Errorf("error")
} else {
ch <- nil
}
}
func main() {
var wg sync.WaitGroup
var err error
errs := make(chan error)
platforms := 2
types := 3
for j := 0; j < platforms; j++ {
wg.Add(1)
for k := 0; k < types; k++ {
wg.Add(1)
n := rand.Intn(2)
go goroutine(n, &wg, errs)
}
for k := 0; k < types; k++ {
wg.Add(1)
n := rand.Intn(2)
go goroutine(n, &wg, errs)
}
}
wg.Wait()
err = <-errs
fmt.Println(err)
}
我应该如何正确地收集错误数组并完成所有等待组?
1条答案
按热度按时间mzaanser1#
Golang渠道与bash管道类似但是与用于将一个命令的输出传输到另一个命令的输入的bash管道相比,Go通道用于在goroutine之间传输一些数据,你可以阅读更多关于通道here的信息,通道有容量,当你没有指定通道的容量时,Go会假设它的容量为0。具有零容量的通道通常称为
unbuffered
通道,而具有非零容量的通道称为buffered
。当通道已满(通道中的元件数目等于通道的容量)时,通道(->errs
)上的所有写入操作阻塞执行流,直到将呈现读取操作(<-errs
)。在您的特定示例中,有一个无缓冲通道(通道容量为0)。因此,任何写操作(
->errs
)将阻塞执行,直到提供一些读操作,因此,当main
函数的流程前进到读操作时,你启动的所有goroutine都会被阻塞,尽管只有一个goroutine可以继续写操作(err = <-errs
)的数据。为了解决这个问题,你可以创建一个额外的goroutine,它同时从通道读取数据和向通道写入数据,如下所示:
此外,我在您的代码中重构了几个错误和不准确之处:
1.你不应该在有错误的通道中写nil。如果你想让
errs
chan只包含错误,那么只有当你的函数执行时有非nil错误时才写。1.你有一个额外的wd.Add(1)作为
j
循环的开始,所以Add
函数和Done
函数之间存在不平衡。1.此外,您在
defer wg.Done()
之后添加defer fmt.Println("defer done")
,但是defer
的构造以与指定的相反的顺序执行,因此将defer fmt.Println("defer done")
放在defer wg.Done()
之前会更正确,这样“defer done”实际上将表示所有先前的defer
都已执行。