Ryan
Ryan

Reputation: 1242

Range over buffered channel in Go is blocking

I must be having a brain block here, but I am getting blocked when iterating over a buffered channel

    results := []search.Book{}
    resultsStream := make(chan []search.Book, 2)
    defer close(resultsStream)

    // parallelize searches to optimize response time
    for _, src := range sources {
        go src.Search(bookName, resultsStream)
    }

    counter := 0
    for sourceResults := range resultsStream {
        counter = counter + 1
        results = append(results, sourceResults...)

        fmt.Println(counter)
    }

    fmt.Println("Never called")

Output

1
2

This proves the 2 sources populate the channel (which is the max capacity). What am I missing here? Never called is, well, never called.

Edit

    var wg sync.WaitGroup
    results := []search.Book{}
    resultsStream := make(chan []search.Book, len(sources))
    defer close(resultsStream)

    // parallelize searches to optimize response time
    for _, src := range sources {
        wg.Add(1)
        go src.Search(bookName, resultsStream, &wg)
    }

    wg.Wait()
    close(resultsStream)
    for sourceResults := range resultsStream {
        results = append(results, sourceResults...)
    }

    c.JSON(http.StatusOK, gin.H{
        "results": results,
    })

Upvotes: 1

Views: 141

Answers (2)

blami
blami

Reputation: 7411

The loop for sourceResults := range resultsStream receives values from the channel repeatedly until it is closed. Once sender is done and closes the channel loop will end.

You can create new channel for each parallel search and once all worker goroutines finish you can close that channel. That will end the receiver loop (NOTE: don't close channel from the receiver side as senders won't know and sending to a closed channel causes panic).

Upvotes: 2

Adeithe
Adeithe

Reputation: 313

When you range over a go channel the for loop is not exited until you either break out of it or the channel is closed using close(resultsStream)

Upvotes: 2

Related Questions