> So you’re shifting the goalposts a little bit, too—awaiting Bar() is only equivalent to a channel receive if there is some other task that actually started the work.
The most correct way of looking at this is that async fucntions return a channel that you can read data from, and await is exactly like a channel read. The magic in async/await comes in the function calling 'await', which is suspended and scheduled to continue later. So, just like in Go, you could create a function that needlessly uses channels but is otherwise synchronous, or you can have a function that uses channels because it actually is doing something in the background.
> Colored functions are when you hijack function call semantics to do asynchronous programming. Go doesn’t do this; the asynchronous behavior has to be done explicitly.
Colored functions are a very general concept. They refer to families of functions which perform the same computation but that need to be written differently for syntactic reasons. Famous examples that have nothing to do with async include C++ const-ness, where you have to write a const and a non-const version of a function to to be able to offer the same functionality for this and for const this.
Go has this with functions which return data versus functions that push data on a channel. If you want your function to be callable in a sync manner, it must return the data directly. If you want it to be callable in an async manner, it must take a channel and push its result on that channel. You can't launch a sync function as a new goroutine and get the result back. You can't call an async function as a regular function and read the result back. So, they are two colors of functions in Go.
More concretely, say you are writing an HTTP client lib. If you want to allow your users to start multiple requests in parallel in a nice fashion, you must write your request function to take a channel and push its response there. If you want to make it easy for your users to just call your function in a sync manner, you must write a function that returns the response as its return value.
Of course, you can implement one in terms of the other, as demonstrated earlier. But you still need to add that wrapping, so your functions have a color.