Original post

In the current implementation, I have 3 channels (ids, results and quit).

There is one goroutine that generate ids and sends them to the ids channel. This routine also receives from quit channel.

There is a pool of workers that consumers these ids, do some http calls and then publish the results to the results channel. Each worker also receives from quit channel.

Ther is another routine that reads from the results and knows the stop criteria. Once the stop criteria is met, I call close(quit), send the output to the channel and end that routine execution.

What I would expect to see? The lines showing the ids and results channels were closed, but I don’t see this in the logs. Also, if I put a break point inside the “case <-quit:” it’s also never reached.

Any idea where is the problem in my implementation?

func main() {
    ids := make(chan int, poolSize)
    res := make(chan SomeStruct)
    quit := make(chan struct{})
    manipulatedResults := make(chan []SomeStruct, 1)
    
    for w := 0; w < poolSize; w++ {
        go doSomeHTTPCall(ids, res, quit)
    }
    go generateIds(ids, quit)
    go doSomethingWithResults(res, quit, manipulatedResults)

    cr := <- manipulatedResults
    close(manipulatedResults)
    // print the manipulatedResults and exit
}

func generateIds(ids chan<- int, quit <-chan struct{}) {
    for {
        select {
        case <-quit:
                log.Print("closing ids channel")
                close(ids)
                return
        default:
                // generate the Ids
        }
    }
}

func doSomeHTTPCall(ids <-chan int, results chan<- SomeStruct, quit <-chan struct{}) {
    for {
        select {
        case id := <-ids:
                // do the http call based on the id received
                results <- result
        case <-quit:
                log.Print("closing results channel")
                close(results)
                return
        }
    }
}

func doSomethingWithResults(results <-chan SomeStruct, quit chan<- struct{}, out chan<- []SomeStruct) {
    var s []SomeStruct
    for t := range results {
        // do something until a criteria is met and then
        break
    }

    close(quit)
    out <- s
}