Golang程序挂起而未完成执行

Golang程序挂起而未完成执行,go,channel,goroutine,Go,Channel,Goroutine,我有以下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.Resp

我有以下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")

}
主程序包
进口(
“fmt”
“net/http”
“时间”
)
var url=[]字符串{
"http://www.google.com/",
"http://golang.org/",
"http://yahoo.com/",
}
类型HttpResponse结构{
url字符串
响应*http.response
错误
状态字符串
}
func asyncHttpGets(url字符串,ch chan*HttpResponse){
客户端:=http.client{}
如果url==”http://www.google.com/" {
time.Sleep(500*time.毫秒)//谷歌关闭了
}
fmt.Printf(“获取%s\n”,url)
resp,err:=client.Get(url)
u:=&HttpResponse{url,resp,err,“fetched”}

ch问题在于,除非通道关闭,否则在for循环中的通道上的测距将永远持续。如果要从通道中准确读取
len(URL)
值,应循环多次:

for i := 0; i < len(urls); i++ {
    fmt.Println(<-ch)
}
对于i:=0;ifmt.Println(另一个好的肮脏诡计是使用
sync.WaitGroup
并根据
goroutine
增加它,然后用
Wait
监视它,完成后它将关闭你的频道,允许下一个代码块运行,我之所以提供这种方法,是因为它不用使用静态数字r在一个类似
len(url)
的循环中,这样您就可以拥有一个可能会改变的动态切片,而不是什么

Wait
close
在各自的goroutine中的原因是,您的代码可以通过您的频道到达
for循环
范围

package main

import (
    "fmt"
    "net/http"
    "time"
    "sync"
)

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, wg *sync.WaitGroup) {
    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")
    wg.Done()
}

func main() {
    fmt.Println("start")
    ch := make(chan *HttpResponse, len(urls))
    var wg sync.WaitGroup
    for _, url := range urls {
        wg.Add(1)
        go asyncHttpGets(url, ch, &wg)
    }

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

    for i := range ch {
        fmt.Println(i)
    }
    fmt.Println("Im done")

}
主程序包
进口(
“fmt”
“net/http”
“时间”
“同步”
)
var url=[]字符串{
"http://www.google.com/",
"http://golang.org/",
"http://yahoo.com/",
}
类型HttpResponse结构{
url字符串
响应*http.response
错误
状态字符串
}
func asyncHttpGets(url字符串,ch chan*HttpResponse,wg*sync.WaitGroup){
客户端:=http.client{}
如果url==”http://www.google.com/" {
time.Sleep(500*time.毫秒)//谷歌关闭了
}
fmt.Printf(“获取%s\n”,url)
resp,err:=client.Get(url)
u:=&HttpResponse{url,resp,err,“fetched”}
中国