The primary difference between async and synchronous I/O is (a) better memory usage due to not having a stack per connection; (b) you can avoid the overhead of context switches to wake up an I/O thread; (c) thread spawning performance is faster due to the kernel not having to be involved. Golang's advantages in (a) and (b) are much less than what is typically thought of as "async I/O", because it still semantically uses a thread-per-connection and so is performing the same operations that a synchronous I/O implementation performs, just with a different implementation strategy.