2015-12-14 61 views
5

我使用sync.WaitGroup, defer wg.Close()wg.Wait()等待我的goroutines完成。Golang應用程序使用sync.WaitGroup&通道永不退出

該程序等待,但它永遠不會退出。

這是我的程序(可運行):

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)

回答

13

你永遠不會關閉fetchedSymbols通道,所以範圍循環永遠不會退出。

處理此問題的一種方法是使用WaitGroup,您必須發出信號指示何時關閉通道。對fetchedSymbols進行測距足以阻止主進程,並且不需要另一個通道或WaitGroup。

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

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

...