2015-12-14 4 views
5

私はsync.WaitGroupdefer wg.Close()wg.Wait()を使用して、私のゴルーチンが完了するのを待ちます。Golangアプリはsync.WaitGroup&channelsを使用しないで終了します

プログラムは待機しますが、終了しません。

これは私のプログラム(実行可能)である:

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チャンネルを閉じることは決してないので、範囲ループは決して終了しません。

これを処理する1つの方法は、すでにチャネルを閉じるタイミングを通知するWaitGroupを使用することです。 fetchedSymbols以上になるとメインの進捗状況をブロックでき、別のチャンネルやWaitGroupは必要ありません。

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

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

... 
関連する問題