←back to thread

Go channels are bad

(www.jtolds.com)
298 points jtolds | 8 comments | | HN request time: 0.901s | source | bottom
1. hamburglar ◴[] No.11211264[source]
Non Go programmer here. Can someone explain the initial goroutine leak that is being addressed? I don't see the issue.
replies(4): >>11211441 #>>11211510 #>>11211514 #>>11211630 #
2. aardvark179 ◴[] No.11211441[source]
I'm not a go programmer, but think of it like this.

You start a game, and that starts a goroutine that goes round in a loop getting scores from a channel. You have players which also have references to the channel and who put scores onto it.

When all the players have left the only thing that has access to the channel is the game's goroutine. It's not consuming CPU itself because it's simply waiting for something to be put on its channel, but it does still have its stack and other resources, and it now has no way to exit.

You can get this sort of resource leak in lots of ways in concurrent systems, and they all essentially boil down to the same thing, a thread or goroutine, or whatever, is waiting on a resource that nothing else has a reference to anymore, and there is no other way end it.

3. r_sreeram ◴[] No.11211510[source]
> Can someone explain the initial goroutine leak that is being addressed?

The "for score := range g.scores {" loop runs forever, since nothing ever closes the g.scores channel. I.e., the "range" only terminates when the channel is explicitly closed. Even if there are no current senders on the channel, and even if nobody else holds a reference to the channel (and thus nobody else could potentially create a new sender and start sending on that channel), Go doesn't realize it (garbage collection doesn't help here). The "range" waits forever.

Thus, all goroutines that run this code (via calls to NewGame(), via "go g.run()") will run forever, and leak, as long as something else in the program is running. When the rest of the program is done, Go will correctly detect that all these leaked goroutines are blocked and thus it's a deadlock, leading Go to panic ("no goroutines can proceed") and terminate.

4. ◴[] No.11211514[source]
5. divan ◴[] No.11211630[source]
It's not actually a leak. It's a program explicitly doing 'run goroutine and don't care of it anymore'. If the program logic wants this - it's ok. If author wants it to finish on some condition, but didn't write the condition code (like in this article) - it's a leak, but it's purely author's mistake.
replies(1): >>11211684 #
6. jtolds ◴[] No.11211684[source]
There is a deliberate leak in the example program. The author was attempting to illustrate that fixing the leak using just channels would be a challenge.
replies(1): >>11211763 #
7. courtf ◴[] No.11211763{3}[source]
Synchronizing access to a memory address isn't really the use-case for channels. I think that's fairly well understood by the Go programmers I work with. This example demonstrates why, but it prefaces the discussion by implying this is the standard practice, which I think is misleading.
replies(1): >>11213854 #
8. jtolds ◴[] No.11213854{4}[source]
I perhaps communicated poorly, but the point of that section was to try and explain that the CSP model (only using channels) was untenable in Go (even though it doesn't necessarily have to be in general), and that you'd almost certainly end up not just using channels in a real program, which it seems you agree with.