Goroutine Leak Profiles(go.dev) |
Goroutine Leak Profiles(go.dev) |
• channels are by default "unbuffered", in that a send needs a waiting recv to actually do the send, and blocks until such. The addition of the buffer prevents the block & permits the goroutine to progress (and eventually exit, and thus, not leak) … so long as the buffer is sufficiently large enough.
• channels do not, AFAICT, realize when the receiver is gone, and will block indefinitely even when there is no receiver. (It is the same "chan" object, I think, in both sender/receiver / there is no distinction. So, the single object is never GC'd.)
• goroutines are not GC'd. (& the code doesn't/can't hold like, a reference or a handle to a goroutine / there is no "join" primitive.)
close() on a chan is "indicate end-of-transmission"; you should only ever use it from the send end. There is no way to explicitly "close" the receive end.
You can use `select` to do a non-blocking sends/receives, but yeah normal sends/receives are blocking.
The problem is that there is pretty much just a subtyping relationship, when you convert a channel to a send or receive channel you don't get a different object, you just get the relevant subset of operations.
> There is no way to explicitly "close" the receive end.
And that's the root cause of half of more of the example issues in TFA. With the ability to close either end of the channel (and to handle closed receivers from the senders, obviously), most of the issues just go away (even more reliably so if that happens for you when the relevant end stops being used).
And not closing channels is also considered idiomatic, per a tour of go:
> Channels aren't like files; you don't usually need to close them.