Proper way to close a channel

Issue

I want to have a bunch of goroutines that will fetch some information from a lot of servers. I’m simplifying the code below so its more readable. It seems to be working perfectly but it panics after all the tasks were completed as I never close the channel. The thing is I am not sure where I should close the same.

I need your help in :

  • Telling me where in the code I should be closing the channel.
  • Telling me if the overall logic of this code seems idiomatically correct.

my code

func main() {
        ch := make(chan string)


        for i:= 0; i < 10 ; i++ {
                go func(c chan <- string,t int){
                        time.Sleep( time.Duration(rand.Intn(3000)) * time.Millisecond )
                        c <- strconv.Itoa(t) + " : Done " + strconv.Itoa(rand.Intn(3000))
                }(ch,i)
        }
        for val := range ch {
                fmt.Println(val)

        }
}

output

$ go run test_channels.go
0 : Done 1694
6 : Done 511
3 : Done 162
2 : Done 89
8 : Done 2728
5 : Done 1274
1 : Done 2211
9 : Done 1445
4 : Done 2237
7 : Done 1106
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
        /home/matias/projects/src/github.com/matias/test/test_channels.go:22 +0x138
exit status 2

Solution

When there’s a single sender on a channel, that sender would normally be responsible for closing the channel if necessary. Remember though that closing a channel isn’t required for cleanup, it’s only if you need to signal that the channel is closed.

When there are multiple senders, you need to coordinate with all of them completing, which you can do with a sync.waitGroup

ch := make(chan string)
var wg sync.WaitGroup

for i := 0; i < 10; i++ {
    wg.Add(1)
    go func(c chan<- string, t int) {
        defer wg.Done()
        time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond)
        c <- strconv.Itoa(t) + " : Done " + strconv.Itoa(rand.Intn(3000))
    }(ch, i)
}

go func() {
    wg.Wait()
    close(ch)
}()

https://play.golang.org/p/ViOtMHbi43C

Answered By – JimB

Answer Checked By – Mildred Charles (GoLangFix Admin)

Leave a Reply

Your email address will not be published.