简体   繁体   English

使用sync.WaitGroup和频道的Golang应用程序永不退出

[英]Golang app using sync.WaitGroup & channels never exits

I use sync.WaitGroup , defer wg.Close() and wg.Wait() to wait for my goroutines to complete. 我使用sync.WaitGroupdefer wg.Close()wg.Wait()来等待我的goroutine完成。

The program do wait, but it never exits. 该程序确实会等待,但是它永远不会退出。

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
}

Shouldn't this program exit when all the quotes have been downloaded? 下载所有报价后,该程序是否应该退出? (FYI: I just started learning GO) (仅供参考:我刚刚开始学习GO)

You're never closing the fetchedSymbols channel, so that range loop will never exit. 您永远不会关闭fetchedSymbols通道,因此范围循环将永远不会退出。

One way to handle this is to use use the WaitGroup you already have to signal when to close the channel. 解决此问题的一种方法是使用WaitGroup,您已经必须在关闭通道时发出信号。 Ranging over fetchedSymbols is enough to block the progress in main, and you don't need another channel or WaitGroup. 覆盖fetchedSymbols足以阻止main的进度,并且您不需要其他通道或WaitGroup。

...
go func() {
    wg.Wait()
    close(fetchedSymbols)
}()

for response := range fetchedSymbols {
    fmt.Println("fetched " + response)
}

...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM