IO channels vs reader/writer
Channels are a good fit for communicating between goroutines. When a program does something simple, like for example reading stdin, doing something with the stream and outputting the result to stdout - then using a channel is an overkill, unnecessarily hurting performance.
As long as the standard library doesn't provide in some place something specific to goroutines communicating with each other, there's no good reason to model simple operations, like those of io.Reader
or io.Writer
using channels, respective to have a channel based method set (API).
Additionally, where needed, the simple implementation can be wrapped in a channel, while the opposite, to "unwrap" a channel implementation back to its primitive is not possible. Also, Go authors obviously like explicitness, leading to performance bottlenecks not being hidden (and surprising).