I agree with almost all of your post except this:
> With Go it doesn't matter if an operation is blocking or non blocking, that fact can totally be abstracted from the client code.
No, it can't, and pretending that it can is misleading in a way that allows large teams of developers to cause themselves real problems.
The only sense in which this is true is that you can write a Go function with a simple signature like this:
func DoSomeStuff (error) {}
And the caller has no idea whether this involves concurrency under the hood (e.g. the function can spawn its own goroutines and channels as it sees fit).
But, make no bones about it: this function blocks until it completes. This means that while this function may do concurrent work it is absolutely a blocking function. This is fine: sometimes blocking functions are good. But you cannot write a non-blocking Go function in the same way.
To make a function non-blocking you can return a channel out of it for the return value to appear on, like this:
func DoSomeStuff (chan error) {}
In this model the caller really doesn't have to care whether the function is synchronous or not (though the fact that it was written this way strongly suggests that it is going to return asynchronously, or at least that the developer believes it will have to in the future).
Except...that return value just there? That's a Future. It's a terrible, half-implemented version of a Future, but that's exactly what it is. It's a promise to return some kind of result at some point when the underlying process has returned.
And if you don't want to block your current goroutine, you cannot block on that channel receive either. That means that you need a callback. There are two patterns for doing that: you could have some kind of central loop that selects over all channels like this and calls the callback functions (boy that looks a lot like Node's event loop, doesn't it!), or you can manually spawn your own callback functions in their own goroutines. Either way, you have callbacks and futures here: you're just building them yourself and calling them something different.
There are lots of good reasons to switch to Go: it's a language that makes lots of developers remarkably productive, it has an ingrained philosophy of building concurrent programs, it's pretty damn fast, and it runs on all kinds of awesome platforms. But claiming that Go has learned something magic and new about how to write concurrent software in such a way that you don't have to care whether your code is async or not is just not true: you always have to care.