3 回答
TA貢獻1829條經驗 獲得超9個贊
您的示例在使用 WaitGroups 方面沒有任何明顯錯誤。只要您調用wg.Add()的數量與您啟動的 goroutine 的數量相同,或者每次啟動新的 goroutine 時都將其增加 1,這應該是正確的。
但是,您在 goroutine 中調用os.Exit和panic針對某些錯誤條件,因此如果您有多個這些正在運行,無論是否使用 WaitGroups,其中任何一個的失敗都會終止所有這些。如果它在沒有恐慌消息的情況下失敗,我會看看這os.Exit(1)條線。
defer wg.Done()在函數開始時使用 go 也是一種很好的做法,這樣即使發生錯誤,goroutine 仍然會減少其計數器。這樣,如果 goroutine 之一返回錯誤,您的主線程將不會在完成時掛起。
TA貢獻1906條經驗 獲得超3個贊
我會在您的示例中進行的一項更改是defer當您使用Done. 我認為這defer ws.Done()應該是您函數中的第一條語句。
我喜歡WaitGroup的簡單。但是,我不喜歡我們需要傳遞對 goroutine 的引用,因為這意味著并發邏輯將與您的業務邏輯混合。
所以我想出了這個通用函數來為我解決這個問題:
// Parallelize parallelizes the function calls
func Parallelize(functions ...func()) {
var waitGroup sync.WaitGroup
waitGroup.Add(len(functions))
defer waitGroup.Wait()
for _, function := range functions {
go func(copy func()) {
defer waitGroup.Done()
copy()
}(function)
}
}
所以你的例子可以這樣解決:
func imageDownloader(uri string, filename string) {
...
io.Copy(outFile, rd)
}
func main() {
functions := []func(){}
list := make([]Object, 5)
for _, object := range list {
function := func(obj Object){
imageDownloader(object.uri, object.filename)
}(object)
functions = append(functions, function)
}
Parallelize(functions...)
fmt.Println("Done")
}
如果你想使用它,你可以在這里找到它https://github.com/shomali11/util
- 3 回答
- 0 關注
- 265 瀏覽
添加回答
舉報
