Sorry for the nitpicking, but:
"One of the things that Go (and Erlang) got right was using channels as the main mechanism for synchronising and communicating between threads."
Erlang doesn't have threads and doesn't use channels either.
Erlang has lightweight processes, which might map onto OS threads (but user code has no control over this).
Erlang uses async communication which is always non-blocking (of course, you can emulate sync communication, the gen_server:call behaviour in the OTP library does that, for example).
Otherwise, spot on! :)