我有以下golang程序;
package main import ( "fmt" "net/http" "time" ) var urls = []string{ "http://www.google.com/", "http://golang.org/", "http://yahoo.com/", } type HttpResponse struct { url string response *http.Response err error status string } func asyncHttpGets(url string, ch chan *HttpResponse) { client := http.Client{} if url == "http://www.google.com/" { time.Sleep(500 * time.Millisecond) //google is down } fmt.Printf("Fetching %s \n", url) resp, err := client.Get(url) u := &HttpResponse{url, resp, err, "fetched"} ch <- u fmt.Println("sent to chan") } func main() { fmt.Println("start") ch := make(chan *HttpResponse, len(urls)) for _, url := range urls { go asyncHttpGets(url, ch) } for i := range ch { fmt.Println(i) } fmt.Println("Im done") }
Run it on Playground
但是,当我运行它; 它挂起(即应该打印的最后一部分Im done
没有运行.)这是终端输出;;
$ go run get.go
start
获取http://yahoo.com/
获取http://golang.org/
获取http://www.google.com/
发送给chan
&{ http://www.google.com / 0xc820144120 fetched}
发送给chan
&{ http://golang.org/ 0xc82008b710 fetched}
发送给chan
&{ http://yahoo.com/ 0xc82008b7a0 fetched}
问题是,除非通道关闭,否则for循环中的通道范围将永远持续.如果len(urls)
要从通道中精确读取值,则应循环多次:
for i := 0; i < len(urls); i++ { fmt.Println(<-ch) }