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