How to end producer from the consumer side

571 views
Skip to first unread message

Jan Pfeifer

unread,
Feb 20, 2012, 7:51:55 PM2/20/12
to golan...@googlegroups.com
hi all, quick question, I have a scenario where the producer should generate numbers indefinitely, until it is told to stop.

Most of the channel producer/consumer examples assume that the producer closes the channels and dies cleanly (on its goroutine).

When I close the channel on the reader instead, i get a panic. Any simple ways around it ?

Pseudo-code:

func producer() chan int {
  c := make(chan int)
  for {
    // produce number
    c <- some_number
  }
}

func main() {
  c := producer()
  for some_condition {
    consume(<-c)
  }
  close(c)
  ...
}

Since I'm going to call this producer zillions of times, I want to make sure whatever memory/resources it uses is reclaimed and cleanly exited when c is closed.

Ideas ?

many thanks in advance :)
Jan

Brad Fitzpatrick

unread,
Feb 20, 2012, 9:01:02 PM2/20/12
to Jan Pfeifer, golan...@googlegroups.com
Use two channels:  one downstream with numbers, and one upstream to tell the sender to stop.

Krzysztof Kowalik

unread,
Feb 20, 2012, 9:45:49 PM2/20/12
to Brad Fitzpatrick, Jan Pfeifer, golan...@googlegroups.com
Two channels are reasonable solution, here's an example: http://play.golang.org/p/sKI05-7v12


2012/2/21 Brad Fitzpatrick <brad...@golang.org>

Brad Fitzpatrick

unread,
Feb 20, 2012, 10:32:17 PM2/20/12
to Krzysztof Kowalik, Jan Pfeifer, golan...@googlegroups.com


On Tue, Feb 21, 2012 at 1:45 PM, Krzysztof Kowalik <ch...@nu7hat.ch> wrote:
Two channels are reasonable solution, here's an example: http://play.golang.org/p/sKI05-7v12

 
except for the close on line 24.  that should go before the return on line 9.

closing is a send operation.

in fact, in Go 1, the line 24 won't even compile, because you (nicely) returned direction-constrained channels from the producer func.

Krzysztof Kowalik

unread,
Feb 20, 2012, 10:43:29 PM2/20/12
to Brad Fitzpatrick, Jan Pfeifer, golan...@googlegroups.com
True, still forgetting that closing directional channel is prohibited. Updated version: http://play.golang.org/p/fT-dHQBYDb

2012/2/21 Brad Fitzpatrick <brad...@golang.org>

Jan Pfeifer

unread,
Feb 21, 2012, 8:59:41 PM2/21/12
to Krzysztof Kowalik, Brad Fitzpatrick, golan...@googlegroups.com
Cool, thanks a ton for the answers :)

The double channel worked fine, with the extra care of closing the quit channel on the consumer side, and the data channel on the producer side.

cheers,   Jan

John Asmuth

unread,
Feb 21, 2012, 9:26:18 PM2/21/12
to golan...@googlegroups.com
You might already realize this, but there is no reason to close the quit channel. It doesn't free any resources or anything. Just send the quit message and then forget about it.

Closing the channel, in fact, just sends a special kind of message and then disallows future messages. If no one keeps track of the quit channel, then no one can send future messages anyway.

fabi...@gmail.com

unread,
Jan 22, 2019, 8:33:35 AM1/22/19
to golang-nuts
Hi, we have the same problem of OP.
But, in the Chris's playground there could be an error, indeed if the consumer 
runs slower of the producer the program ends in a deadlock.

To force this behavior just add a time.Sleep() after the foor loop in main.
--> https://play.golang.org/p/A3i6TEyGQm_L

Am I wrong?

Thanks for the help.

Josh Humphries

unread,
Jan 22, 2019, 11:22:40 AM1/22/19
to fabi...@gmail.com, golang-nuts
On Tue, Jan 22, 2019 at 8:33 AM <fabi...@gmail.com> wrote:
Hi, we have the same problem of OP.
But, in the Chris's playground there could be an error, indeed if the consumer 
runs slower of the producer the program ends in a deadlock.

To force this behavior just add a time.Sleep() after the foor loop in main.
--> https://play.golang.org/p/A3i6TEyGQm_L

Am I wrong?

This is wrong because it's not using the select expression in the producer correctly. Instead of a default case with unconditional channel write, you need the channel write to be one of the cases. Like so:

Thanks for the help.


Il giorno martedì 21 febbraio 2012 01:51:55 UTC+1, Jan ha scritto:
hi all, quick question, I have a scenario where the producer should generate numbers indefinitely, until it is told to stop.

Most of the channel producer/consumer examples assume that the producer closes the channels and dies cleanly (on its goroutine).

When I close the channel on the reader instead, i get a panic. Any simple ways around it ?

Pseudo-code:

func producer() chan int {
  c := make(chan int)
  for {
    // produce number
    c <- some_number
  }
}

func main() {
  c := producer()
  for some_condition {
    consume(<-c)
  }
  close(c)
  ...
}

Since I'm going to call this producer zillions of times, I want to make sure whatever memory/resources it uses is reclaimed and cleanly exited when c is closed.

Ideas ?

many thanks in advance :)
Jan

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jon Betti

unread,
Jan 22, 2019, 11:46:33 AM1/22/19
to Josh Humphries, fabi...@gmail.com, golang-nuts
I'd also tend toward passing in a context to the producer rather than returning a "kill" channel. That way you get correct cancellation when you begin to string together multiple producers. I'd recommend reading https://blog.golang.org/pipelines in any case.

Reply all
Reply to author
Forward
0 new messages