Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to receive data from multiple channels using for/select syntax?

I have case where I need to receive data on multiple channels and somehow quit infinite for loop.

Here is simple example:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    sumChannel := make(chan int)
    productChannel := make(chan int)

    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go compute(i, sumChannel, productChannel, &wg)
    }

    go func() {
        wg.Wait()
        close(sumChannel)
        close(productChannel)
    }()

    for {
        select {
        case <-sumChannel:
            fmt.Println("sum")
        case <-productChannel:
            fmt.Println("prod")
        }
    }
}

func compute(i int, sumChannel chan int, productChannel chan int, wg *sync.WaitGroup) {
    time.Sleep(2 * time.Second)
    sumChannel <- i + i
    productChannel <- i * i
    wg.Done()
}

The problem is I get infinite for loop. I know that I should create new channel (for instance,quit) for quitting from loop. But, I really don’t understand where to put signal to quit, because I don’t know exact place where I can be sure that all goroutines finished.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

If you run the for loop in a go routine and then wait for the compute go routines to finish, you can cancel the loop from there:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    sumChannel := make(chan int)
    productChannel := make(chan int)
    closeChannel := make(chan bool)

    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go compute(i, sumChannel, productChannel, &wg)
    }

    go func() {
        for {
            select {
            case <-sumChannel:
                fmt.Println("sum")
            case <-productChannel:
                fmt.Println("prod")
            case <-closeChannel:
                fmt.Println("break")
                break
            }
        }
    }()

    wg.Wait()
    closeChannel <- true

    fmt.Println("done")
}

func compute(i int, sumChannel chan int, productChannel chan int, wg *sync.WaitGroup) {
    time.Sleep(2 * time.Second)
    sumChannel <- i + i
    productChannel <- i * i
    wg.Done()
}

Run it

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading