Hacker News new | past | comments | ask | show | jobs | submit login

> In Go, we can do this by closing a channel, because a receive operation on a closed channel can always proceed immediately, yielding the element type's zero value.

    for n := range c {
        select {
        case out <- n:
        case <-done:
        }
    }
This, is brilliant.



I wasn't quite getting that code when I first read it.

Now I can see it allows you do "discard" all the pending reads from the input channel (and avoid writing to a possibly-closed 'out' channel), but wouldn't it be better to break the loop in this case for an immediate exit?

i.e. go for 'interrupt' semantics, rather than 'drain'?


Yes, interrupt is better, and the article explains how to do that a few paragraphs later:

        for n := range in {
            select {
            case out <- n * n:
            case <-done:
                return
            }
        }
If you allow pipeline stages to interrupt their receive loop instead of draining the inbound channel, then _all_ send operations need to be governed by done. Otherwise the interrupted receive loop may block the upstream sender.


The loop (particularly `range c`) keeps getting element out of `c` and assigning it to `n`. If it's "done", then `n` wouldn't be sent into `out`, but still gets read from the channel `c` constantly. In other words, it's the loop itself that makes sure everything sent into channel `c` is consumed.

If `break` is used, for loop is terminated once it's "done", hence nothing would be reading from channel `c`. The previous station in the pipeline would then block at sending operation.


I think its so that the channel is empty, and will have no references so it will be garbage collected.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: