What is the preferred syntax to run code in parallel with goroutine?

Issue

Let’s say I need to call a function twice. The usual way to do it would be:

func main() {
    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        doSomething(A)          
        wg.Done()
    }()

    go func() {
        doSomething(B)
        wg.Done()
    }()
    wg.Wait()
}

But what about writing it like this ?

func main() {
    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        doSomething(A)          
        wg.Done()
    }()

    doSomething(B)
    wg.Done()
    wg.Wait()
}

We spare ourselves the creation of one goroutines, while making use of the main goroutine. But I’ve never seen it written like that in any tutorial. Is it wrong to do this? I’ve done tests and the output are just as I though the same.

Solution

Both are correct. The first form is cleaner and scales well if you intend to extend your code later, e.g. if you later decide you want to launch not 2 but 3 or 4 or N goroutines, the code will not change in structure, you just add the additional goroutines.

Another reason why the first form is “popular” is because often after launching the “worker” goroutines there are more things to do which may be executed on this goroutine (before wg.Done() is called).

The 2nd form on the other hand is more efficient, as it only launches one additional goroutine. Goroutines are lightweight, cheap, but they are not “free”. This may be improved further by using the WaitGroup to only “track” the launched goroutine, obviously the “main” that calls wg.Wait() does not need to wait for itself explicitly. And if only 1 goroutine remains, you may use other synchronization means instead of WaitGroup (e.g. a channel).

So basically if performance is critial, use the 2nd approach.

Answered By – icza

Answer Checked By – Timothy Miller (GoLangFix Admin)

Leave a Reply

Your email address will not be published.