使用 sync.WaitGroup 和频道的 Golang 应用程序永远不会退出
Golang app using sync.WaitGroup & channels never exits
我使用 sync.WaitGroup
、defer wg.Close()
和 wg.Wait()
来等待我的 goroutines 完成。
程序会等待,但它永远不会退出。
这是我的程序(可运行):
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
}
当所有的报价都下载完后,这个程序不应该退出吗? (仅供参考:我刚开始学习围棋)
您永远不会关闭 fetchedSymbols
通道,因此范围循环永远不会退出。
处理此问题的一种方法是使用您已经必须在关闭通道时发出信号的 WaitGroup。超过 fetchedSymbols
就足以阻止 main 的进度,您不需要另一个频道或 WaitGroup。
...
go func() {
wg.Wait()
close(fetchedSymbols)
}()
for response := range fetchedSymbols {
fmt.Println("fetched " + response)
}
...
我使用 sync.WaitGroup
、defer wg.Close()
和 wg.Wait()
来等待我的 goroutines 完成。
程序会等待,但它永远不会退出。
这是我的程序(可运行):
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
}
当所有的报价都下载完后,这个程序不应该退出吗? (仅供参考:我刚开始学习围棋)
您永远不会关闭 fetchedSymbols
通道,因此范围循环永远不会退出。
处理此问题的一种方法是使用您已经必须在关闭通道时发出信号的 WaitGroup。超过 fetchedSymbols
就足以阻止 main 的进度,您不需要另一个频道或 WaitGroup。
...
go func() {
wg.Wait()
close(fetchedSymbols)
}()
for response := range fetchedSymbols {
fmt.Println("fetched " + response)
}
...