I need to start a huge amount of goroutines and wait for their termination. The intuitive way seems to use a channel to wait till all of them are finished :
pack
@tjameson did a great job explaining how to use WaitGroup
, how to pass a reference to your WaitGroup
object to your function. The one change I would make to his example is leverage defer
when you are Done
. I think this defer ws.Done()
should be the first statement in your function.
I like WaitGroup
's simplicity. However, I do not like that we need to pass the reference to the goroutine because that would mean that the concurrency logic would be mixed with your business logic.
So I came up with this generic function to solve this problem for me:
// 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)
}
}
So your example could be solved this way:
type Object struct {
//data
}
func (obj *Object) Update() {
//update data
time.Sleep(time.Second)
fmt.Println("Update done")
return
}
func main() {
functions := []func(){}
list := make([]Object, 5)
for _, object := range list {
function := func(obj Object){ object.Update() }(object)
functions = append(functions, function)
}
Parallelize(functions...)
fmt.Println("Group done")
}
If you would like to use it, you can find it here https://github.com/shomali11/util