Golang application using sync.WaitGroup & channels never exits

I use sync.WaitGroup , defer wg.Close() and wg.Wait() to wait for my goroutines to complete.

The program is waiting, but it will never exit.

This is my program (runnable):

 package main import ( "fmt" "io" "log" "net/http" "os" "sync" ) var symbols = []string{ "ASSA-B.ST", "ELUX-B.ST", "HM-B.ST", } func main() { fmt.Println("fetching quotes...") fetchedSymbols := make(chan string) var wg sync.WaitGroup wg.Add(len(symbols)) for _, symbol := range symbols { go fetchSymbol(symbol, &wg, fetchedSymbols) } for response := range fetchedSymbols { fmt.Println("fetched " + response) } wg.Wait() fmt.Println("done") } func fetchSymbol(symbol string, wg *sync.WaitGroup, c chan<- string) { defer wg.Done() resp, err := http.Get("http://ichart.yahoo.com/table.csv?s=" + symbol + "&a=0&b=1&c=2000") defer resp.Body.Close() if err != nil { log.Fatal(err) } out, err := os.Create("./stock-quotes/" + symbol + ".csv") defer out.Close() if err != nil { log.Fatal(err) } io.Copy(out, resp.Body) c <- symbol } 

Should this program not exit when all quotes have been loaded? (FYI: I just started learning GO)

+5
source share
1 answer

You never close the fetchedSymbols channel, so the range loop will never exit.

One way to handle this is to use WaitGroup, with which you should already signal when to close the channel. In order to block progress in the main, it is enough to exceed fetchedSymbols , and you do not need another channel or WaitGroup.

 ... go func() { wg.Wait() close(fetchedSymbols) }() for response := range fetchedSymbols { fmt.Println("fetched " + response) } ... 
+13
source

Source: https://habr.com/ru/post/1238195/


All Articles