If you run a microbenchmark which seems like what has been done, then channels look slow.
If you try the contention with thousands of goroutines on a high core count machine, there is a significant inflection point where channels start outperforming sync.Mutex
The reason is that sync.Mutex, if left to wait long enough will enter a slow code path and if memory serves, will call out to a kernel futex. The channel will not do this because the mutex that a channel is built with is exists in the go runtime - that's the special sauce the author is complaining doesn't exist but didn't try hard enough to seek it out.
Anecdotally, we have ~2m lines of Go and use channels extensively in a message passing style. We do not use channels to increment a shared number, because that's ridiculous and the author is disingenuous in their contrived example. No serious Go shop is using a channel for that.