Home > Mobile >  Range over buffered channel in Go is blocking
Range over buffered channel in Go is blocking

Time:12-21

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,
    })

CodePudding user response:

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

CodePudding user response:

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)

  •  Tags:  
  • go
  • Related