←back to thread

Go channels are bad

(www.jtolds.com)
298 points jtolds | 4 comments | | HN request time: 0s | source
Show context
sagichmal ◴[] No.11211112[source]
This is a frustrating and overly-exasperated post which reaches conclusions that have always been part of the Go canon. APIs should be designed synchronously, and the callers should orchestrate concurrency if they choose -- yes! Channels are useful in some circumstances, but if you just want to synchronize access to shared memory (like the author's example) then you should just use a mutex -- yes! These are well understood truths.

Novices to the language have a tendency to overuse channels. Here is Andrew Gerrand addressing precisely this point two years ago at GopherCon: https://www.youtube.com/watch?v=u-kkf76TDHE&t=815

Neither the referenced performance characteristics via Tyler Treat, nor the FUD surrounding channel-based program architecture, invalidate channels generally. One does have to think carefully about ownership hierarchies: only one goroutine gets to close the channel. And if it's in a hot loop, a channel will always perform worse than a mutex: channels use mutexes internally. But plenty of problems are solved very elegantly with channel-based CSP-style message passing.

It's unfortunate that articles like this are written and gain traction. The explicit instruction to [new] Go programmers is that they should avoid channels, even that they are badly implemented, and both of those things are false.

replies(7): >>11211239 #>>11211262 #>>11211272 #>>11211656 #>>11211660 #>>11214091 #>>11228064 #
bad_user ◴[] No.11211262[source]
> APIs should be designed synchronously, and the callers should orchestrate concurrency if they choose

Wait, why would you say that?

In general, if "orchestrating concurrency" involves guarding access to shared mutable state, then you can't orchestrate it at the callers site. It would be a massive encapsulation leak, because synchronization is not composable, requires special knowledge, plus you don't necessarily know how to synchronize unless you have knowledge about internals. Furthermore, because it is after the fact, your only choice of handling it is by means of mutexes, which has really terrible performance characteristics. Even if you could do ordering by other means, you end up paying the price of LOCK XCHG or whatever mutexes translate to, not to mention that you'll have problems if you want (soft) real-time behavior, because now you can end up with both dead-locks and live-locks.

And this brings us to another problem. If you end up doing such synchronization in Go, then Go's M:N multi-threading ends up doing more harm than good, because if you need such synchronization, you also need to fine tune your thread-pools and at this point 1:1 would be better. On top of 1:1 platforms you can build M:N solutions, but it doesn't work well in the other direction.

> Novices to the language have a tendency to overuse channels

Novices to software development have a tendency to overuse mutexes as well.

replies(4): >>11211326 #>>11211353 #>>11211663 #>>11222537 #
pmarreck ◴[] No.11211663[source]
Reading this... only makes me gladder that I'm pursuing work in the Erlang/Elixir space, where messaging "just works" and concurrency "just works" and immutability "just works" (and new processes take a microsecond to spin up) and tearing anything down is basically a nonissue as failure is embraced and logged at every turn and cascading teardowns simply happen automatically depending on how the processes are linked

and all this turns out to be a really amazing system of paradigms when designing apps to work in the real world

replies(1): >>11212034 #
svanderbleek ◴[] No.11212034[source]
It "just works" in Go too, minus immutability, but congrats on your technology decision. You don't get type checking but c'est la vie.
replies(3): >>11212486 #>>11213900 #>>11214370 #
1. pmarreck ◴[] No.11213900{3}[source]
Restricting input based on type hierarchies can reduce a certain class of bugs, yes, but careful use of guards as well as typespecs and unit test coverage (which you should have, anyway) can accomplish much of what type restrictions can
replies(1): >>11214838 #
2. pmarreck ◴[] No.11214838[source]
Was something I said factually wrong? User im_down_w_otp put up an example of what I'm talking about (minus the unit testing) so what gives?
replies(1): >>11216739 #
3. sagichmal ◴[] No.11216739[source]
I suspect dismissing static typing whole cloth with "unit tests and certain guards can give you most of the benefits" comes off badly to some people.
replies(1): >>11225202 #
4. pmarreck ◴[] No.11225202{3}[source]
I don't see how "can accomplish much of what type restrictions can" is the equivalent of "dismissing static typing whole cloth"

I choose wording carefully for a reason