Rendered at 20:15:52 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
deathanatos 15 hours ago [-]
I'm coming predominately from other languages, so it took me a hot minute to figure out what the various bug were.
• 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.)
LukeShu 11 hours ago [-]
"<-chan TYPE" is the receive end, "chan<- TYPE" is the send end, "chan TYPE" without an arrow can be used for either.
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.
masklinn 8 hours ago [-]
> "<-chan TYPE" is the receive end, "chan<- TYPE" is the send end, "chan TYPE" without an arrow can be used for either.
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).
mitxela 7 hours ago [-]
It's still the same object pointer. The GC can't force close a channel when it has no readable references left.
masklinn 14 hours ago [-]
(2) has a bit more nuance to it: you can close channels… but the langage is designed for that to only be ok on single senders, a receiver can gracefully handle a closed channel (an iteration will just stop, a receive can use the 2-valued form to get the information), a sender will always straight up panic. Aka go channels are designed for fan-out.
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.
sethammons 10 hours ago [-]
General rule: never call a goroutine without understanding how it will close.
• 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.