Why do I need to do an additional for loop over the results of my go routine/channel to display all results?

Issue

A quick explanation of the code:

  • I’m ranging over db.Feeds() which is a list of RSS feed urls.
  • I’m getting the feeds in the getFeeds() function via a goroutine
  • The output of getFeeds() is returned into the rss channel
  • I then print the RSS information

    func main() {
        rss := make(chan feed)
    
        for _, url := range db.Feeds() {
            go getFeeds(url, rss)
        }
    
        for range db.Feeds() {
            newFeed := <-rss
            fmt.Println(newFeed.Channel.Title, newFeed.Channel.Description)
        }
    }
    

My question is as follows: When I directly print the newFeed variable it doesn’t display all results from the rss channel, only the first one.

I seem to have to range over db.Feeds() (the list of RSS feed urls) and print the channel results from the for loop containing the go getFeeds() for it to display all the results.

Why is this the case? I would have though for each loop of the range, it would return into the rss channel and print the results without having to range over db.Feeds() a second time?

Any clarification greatly helped, I’m new to Go! Loving it, but not got my head around some aspects of the language yet.

Solution

The <-channel operator consumes a single element from a channel. If you want to keep reading until the channel is closed, you need to range over it.

However, you need to range over the channel itself, not db.Feeds:

for newFeed := range rss {
    fmt.Println(newFeed.Channel.Title, newFeed.Channel.Description)
}

Technically, repeating the read newFeed := <-rss multiple times is what is really working.

Currently, this only works because you have the same number of feeds as you have elements written to rss. If instead the number of elements did not match, you would either exit before reading all elements, or wait for more when there are no more coming.

You’ll also want some type of coordination to make sure you close the rss channel when all getFeeds functions are done.

I strongly recommend you take the Go tour, especially the concurrency section

Answered By – Marc

Answer Checked By – Katrina (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.