Looping vs. Waitgroup to Wait and Read from Channel

Hi, I’m wondering if this code would read better using Waitgroup instead of looping in order to ensure the main routine doesn’t return before the go funcs return. I am playing with piping channels by pretending to get a title and get a boolean if a title exists from a website.

Specifically in the below code I loop through 5 times to read from the channel anyway, so what would be the use of a Waitgroup? Would I wait, then range over the last channel in the pipe?

package main

import (
	"fmt"
	"time"
)

// Mock getting some data from, say a website.
func getTitle(titlesChan chan<- string) {
	time.Sleep(1 * time.Second)
	titlesChan <- "Google"
}

func hasTitle(titlesChan <-chan string, hasChan chan<- bool) {
	time.Sleep(1 * time.Second)
	titles := <-titlesChan
	hasChan <- titles != ""
}

func main() {
	titleChan := make(chan string)
	hasTitleChan := make(chan bool)
       
        // Pretend I'm getting titles and checking for existence 5 times.
	for x := 1; x < 5; x++ {
		go getTitle(titleChan)
		go hasTitle(titleChan, hasTitleChan)
	}
	for x := 1; x < 5; x++ {
		fmt.Println(<-hasTitleChan)
		if x == 4 {
			close(hasTitleChan)
		}
	}

}

https://play.golang.org/p/MuIe_GrEWtY

Hi @kahunacohen, can you give us more context?
Why are you getting the title 5 times at the same time?
Can you use a rest client with retries and delay between retries?
Something like this:
https://play.golang.org/p/sk_2Zo3qhc4

sorry it’s really just a mock. Trying to understand piping channels. The 5 times is arbitrary. I am simulating what API calls, parsing etc. might look like. Like, let’s say I am looping through an array of 5 urls…My real question is the use of the loop to read from the channel and close the channel so that the main fn doesn’t exit before the go functions are done executing. Is there a better way using WaitGroup? I can see the use-case if you don’t need data from the channel, but you have to read the data anyway in a loop right?

In this case I don’t believe you need a WaitGroup.
You can move the close function outside the loop.
Something like this:

package main

import (
	"fmt"
)

type titleResult struct {
	title   string
	results bool
}

func getTitle(titlesIn <-chan string, titleResultOutput chan<- titleResult) {
	for x := range titlesIn {
		// get info of the title X
		titleResultOutput <- titleResult{title: x, results: true}
	}
}

func main() {
	workersCount := 5

	// titles to get
	titleNames := []string{"google", "saya", "ml", "google_2", "saya_2", "ml_2"}

	titles := make(chan string, len(titleNames))
	titlesResults := make(chan titleResult, len(titleNames))

	// create N workers
	for x := 1; x <= workersCount; x++ {
		go getTitle(titles, titlesResults)
	}

	// Send Titles to Workers
	go func() {
		for _, title := range titleNames {
			titles <- title
		}
		close(titles)
	}()

	// Process Results
	for x := 1; x <= len(titleNames); x++ {
		getResult := <-titlesResults // this line blocks the execution until the worker process the title
		fmt.Printf("%d - %+v\n", x, getResult)
	}
	close(titlesResults)
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.