2015-12-14 4 views
5

Ich benutze sync.WaitGroup, defer wg.Close() und wg.Wait() warten auf meine Goroutinen abzuschließen.Golang App mit sync.WaitGroup & Kanäle nie beendet

Das Programm warten, aber es wird nie beendet.

Das ist mein Programm (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 
} 

Sollte dieses Programm nicht beendet werden, wenn alle Zitate heruntergeladen wurden? (FYI: Ich fing gerade an, GO zu lernen)

Antwort

13

Sie schließen nie den fetchedSymbols Kanal, damit Bereichsschleife nie beendet wird.

Eine Möglichkeit, dies zu umgehen, ist die Verwendung der WaitGroup, die Sie bereits signalisieren müssen, wann der Kanal geschlossen werden soll. Rangieren über fetchedSymbols ist genug, um den Fortschritt in main zu blockieren, und Sie brauchen keinen weiteren Kanal oder eine WaitGroup.

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

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

...