Now that we’ve talked about what goroutines are and aren’t, lets look at the details of a Go statement:
Go statements
…
The expression must be a function or method call; it cannot be parenthesized.
This is important! The expression must be a functino or method call. Not simply the name of a function or method. That is to say, this:
go foo()
not that:
go foo
This may feel pretty natural, but it’s easy (at leat for me) to forget sometimes. Especially when using an anonymous function. I very frequently make the mistake of typing this:
go func() {
/* do a thing */
}
which is invalid. I need to add the ()
at the end to make it a function call:
go func() {
/* do a thing */
}()
… Calls of built-in functions are restricted as for expression statements.
If you need to use a built-in function, then, you’ll need to wrap it in another (likely anonymous) function:
go func() {
close(myChannel)
}()
(Although honestly, I’m not aware of any reason to ever call a builtin function by iteslf in a new goroutine).
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.
This is, of course, what makes go statements special. The functions called with such a statement run independently of the current program execution flow. This is the primary Go way to write asynchronous code.
Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)