Search code examples
goconcurrencygoroutine

Goroutine concept: direct call vs call using function literal


What are the basic differences between below two codes? Somehow, in the second example demo_process2() is never called but it works fine in the first example.

    1.
go func() {
    Must(demo_process1())
}()

demo_process2()
    2.
go Must(demo_process1())
demo_process2()

where Must():

func Must(err error) {
    if err != nil {
        panic(err)
    }
}

Solution

  • Spec: Go statements:

    The function value and parameters are evaluated as usual in the calling goroutine, but unlike with a regular call, program execution does not wait for the invoked function to complete. Instead, the function begins executing independently in a new goroutine.

    In your first example you launch an anonymous function (a function literal) with no parameters as a new goroutine. Must() and demo_process1() are called inside that, concurrently with demo_process2() (which is executed in the "original" goroutine).

    In your second example however:

    go Must(demo_process1())
    demo_process2()
    

    The function launched as a goroutine is Must(), and its parameters are evaluated in the calling goroutine. Parameter of Must() is the return value of demo_process1(), which means demo_process1() is called and waited for first before a new goroutine is launched. Only when it returns may the new goroutine be started and demo_process2() be called (on the "original" goroutine).

    All in all, in the second example demo_process1() and demo_process2() are not running concurrently but sequentially, in the same goroutine. Only the Must() is executed on a new goroutine (concurrently with demo_process2()).