【问题标题】:Golang app using sync.WaitGroup & channels never exits使用 sync.WaitGroup 和频道的 Golang 应用程序永远不会退出
【发布时间】:2015-12-14 22:03:27
【问题描述】:

我使用 sync.WaitGroupdefer wg.Close()wg.Wait() 来等待我的 goroutine 完成。

程序会等待,但它永远不会退出。

这是我的程序(可运行):

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
}

当所有的报价都下载完毕后,这个程序不应该退出吗? (仅供参考:我刚开始学习 GO)

【问题讨论】:

    标签: go goroutine


    【解决方案1】:

    您永远不会关闭fetchedSymbols 频道,因此范围循环将永远不会退出。

    处理此问题的一种方法是使用 WaitGroup,您必须在何时关闭通道时发出信号。范围超过fetchedSymbols 就足以阻止 main 中的进度,并且您不需要另一个频道或 WaitGroup。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-26
      • 1970-01-01
      • 1970-01-01
      • 2017-02-23
      • 2020-05-06
      • 2018-06-09
      • 1970-01-01
      • 2020-05-04
      相关资源
      最近更新 更多