Top
Best
New

Posted by mpweiher 4/13/2025

Problems with Go channels (2016)(www.jtolio.com)
160 points | 197 commentspage 3
politician 4/13/2025|
My rule of thumb is that the goroutine that writes to a channel is responsible for closing it. In this case, a deferred call to close the channel in HandlePlayer is sufficient.

Still, this example has other issues (naked range over a channel?!) potentially contributing to the author’s confusion.

However, this post was also written almost a decade ago, so perhaps it’s a result of being new to the language? If I cared to look, I’d probably be able to find the corresponding HN thread from that year full of arguments about this, hah.

sapiogram 4/13/2025||
> My rule of thumb is that the goroutine that writes to a channel is responsible for closing it. In this case, a deferred call to close the channel in HandlePlayer is sufficient.

This isn't your rule of thumb, it's the only practical way to do it. The problems arise when you have multiple goroutines writing to a channel, which is the case here.

> Still, this example has other issues (naked range over a channel?!) potentially contributing to the author’s confusion.

You sound way more confused than the author. I think you've misunderstood what the (admittedly very abstract) example is supposed to be doing.

sateesh 4/13/2025||
> In this case, a deferred call to close the channel in HandlePlayer is sufficient

It is not clear from the example, but I presume there would multiple players, i.e there will calls of the form:

  g.HandlePlayer(p1)
  g.HandlePlayer(p2)
  ..
in such a case one player closing the channel would affect rest of the producers too.
GoRocks12 4/13/2025||
Amusing, like the Blub paradox but backwards. Programmers with no experience in Go think they can critique it before they've understood it.

If you don't understand how to use channels, you should learn first. I agree that you might have to learn by experimenting yourself, and that

a) there is a small design flaw in Go channels, but one that is easily fixed; and

b) the standard documentation does not teach good practices for using channels.

First, the design flaw: close(channel) should be idempotent. It is not. Is this a fatal flaw? Hardly. The work around is trivial. Create a wrapper struct with a mutex that allows you to call Close() on the struct, and that effects an idempotent close of the member channel. Yes this is a bit of work, but you do it once, put it in a re-usable library, and never bother to think much about it again.

b) poor recommended practices (range over channel). The original article makes this mistake, and it is what causes his problem: you can never use range over a channel in production code. You must always do any select on a channel alongside a shutdown (bailout) channel, so there will always be at least two channels being select-ed on.

So yes. The docs could be better. It was immediately obvious to me when I learned Go 12 years ago that nobody at Google ever shuts down their services deliberately. Fortunately I was learning Test Driven Development at the time. So I was forced to figure out the above two rules pretty quickly.

Once those two trivial fixes are in place, Go sails. There are Go libraries on github that do this for you. You don't even have to think. But you should.

Handling errors is only as verbose as you want it to be. You do realize you can call a function instead of writing if err != nil so much, right? Sheesh.

Go _is_ something of a sharp tool. Maybe we need to put a warning on it: for mature audiences only.

maleldil 4/14/2025||
> Go _is_ something of a sharp tool. Maybe we need to put a warning on it: for mature audiences only

This has been said for other languages, and it turns out no one is mature enough to consistently make it work without issues. The world has moved on; we can have proper tools that won't shoot your leg off.

Why risk misusing the sharp tool when you can just use something safe to accomplish the same thing?

pdimitar 4/16/2025||
Indeed. Elixir for most things (as it steps on Erlang's excellent runtime and has hygienic macros and an an amazing ecosystem), and when performance and system footprint really matters, get out the big guns -- Rust.

I quickly fell in love with Golang... and quickly fell out of love with it as well. It's a language that is super easy to love but it just does not seem to be suited for big codebases at all.

jfauwasdf 4/14/2025||
> you can never use range over a channel in production code. You must always do any select on a channel alongside a shutdown (bailout) channel, so there will always be at least two channels being select-ed on.

What if you spawned a new goroutine that waits for a waitgroup to complete and then closes the channel?

Saul1998zx 4/15/2025||
6451937099
zerr 4/13/2025||
Is the tl;dr: instead of channels, just use mutexes (and a shared state) explicitly with goroutines?
guilhas 4/13/2025|
Use the one that fits your problem https://go.dev/wiki/MutexOrChannel

But in any case you will end up using a wrapper on either

zerr 4/14/2025||
So akin to Erlang processes.
Saul1998zx 4/15/2025|
Si