how to avoid sending on a closed channel

2,038 views
Skip to first unread message

long...@gmail.com

unread,
Aug 14, 2015, 9:43:49 AM8/14/15
to golang-nuts
I can't find a design to avoid sending on a closed channel. Consider following scenario:

There are 3 go routines, producer, consumer, main. And a channel C. 
"producer" sends new task to channel C
"consumer" receives a task from channel C, and processing it. 
"main" is responsible for run cleanup when shutdown.

Following execution sequence may cause a "send on closed channel" panic.
1. "consumer" fetched a job from channel C then processing, the it is slow
1. "producer" trying to send, but blocked on C because there is no buffer available in channel C
2. service is going to shutdown, so "main" close the channel C
3. when the channel C is closed, the "producer" is waked up, and panic. If no recover() called, the job is lost too.

The code can be found here:
http://play.golang.org/p/MCQ2U33v2m

Do I have to wrap every send operation with a recover() to detect the panic? 

Ian Davis

unread,
Aug 14, 2015, 9:48:18 AM8/14/15
to golan...@googlegroups.com
Generally the producer should be in charge of closing the channel so it knows not to send on it. Main could signal the producer to close the channel.
 
Ian

Jérôme Champion

unread,
Aug 14, 2015, 9:54:58 AM8/14/15
to golang-nuts
The procducer should close the channel.
I think "main" should notify "producer" that it has to stop. Producer can have a select like:

select {
case c <- 42:
break
case <-quit:
break

Jérôme Champion

unread,
Aug 14, 2015, 9:56:47 AM8/14/15
to golang-nuts
And of course closing the channel in the <-quit case.

Roberto Zanotto

unread,
Aug 14, 2015, 1:46:52 PM8/14/15
to golang-nuts
Normally you'd want to structure it like this: https://play.golang.org/p/CEO_flcINB

It's common to use a separate channel to signal when you are done. In the example I wrote, if we closed "c" instead of using quit, the consumer would have received a zero value message, which is what happens when you read from a closed channel. So we wouldn't be able to distinguish between receiving 0 and the channel being closed.
It's fun to write concurrent programs in Go, but at first it takes a bit of time to get comfortable with asynchronous/synchronous communication, goroutines and co. I'd suggest looking for some videos and tutorials online.
Cheers

Matt Harden

unread,
Aug 14, 2015, 2:21:49 PM8/14/15
to Roberto Zanotto, golang-nuts
No, that's not idiomatic. It is possible to distinguish between a zero value sent on a channel and the channel closing by using comma-ok syntax:

v, ok := <-mychannel

For a consumer of a single channel as in your example, it would be more usual to use range(), which exits the for loop when the channel is closed. https://play.golang.org/p/3wQNexfISO

--
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.

Roberto Zanotto

unread,
Aug 14, 2015, 2:34:00 PM8/14/15
to golang-nuts, roby...@gmail.com
Ooops, thanks for the corrections :)
Reply all
Reply to author
Forward
0 new messages