为什么此for循环永远不会退出?

时间:2018-07-12 02:28:32

标签: for-loop go

有以下代码,使用它们会导致无限循环。来自通道的值是正确的,变量和的值也是正确的。所有goroutine最终都不会出错。

func responseHandler(w http.ResponseWriter, r *http.Request) {
    var c = make(chan string)
    for i := 0; i < 100; i++ {
        url := fmt.Sprintf("someurl/page%v/etc", i)
        go parse(url, i, c)
        if i%5 == 0 {
            time.Sleep(1000 * time.Millisecond)
        }
    }
    for range c {
        sum = append(sum, <-c)
    }
    fmt.Println("Exit from channel wait")
    fmt.Fprintln(w, sum)
}

func parse(url string, num int, c chan string) {
    response, err1 := http.Get(url)
    if err1 != nil {
        log.Fatal(err1)
    }
    defer response.Body.Close()

    if response.StatusCode != 200 {
        log.Fatalf("status code error: %d %s", response.StatusCode, 
response.Status)
    }

    res, err := DecodeHTMLBody(response.Body, "windows-1251")

    doc, err := goquery.NewDocumentFromReader(res)
    if err != nil {
        log.Fatal(err)
    }

    doc.Find(".b-advItem__content").Each(func(i int, s *goquery.Selection) {
        title := strings.TrimSpace(s.Find(".someclass").Text())
        price := strings.TrimSpace(s.Find(".someclass").Text())
        formatPrice := parsePrice(price)
        c <- fmt.Sprintf("output %d: %s:%s\n", i, title, formatPrice)
    })
    fmt.Printf("Channel %d - exit\n", num)

总和-全局[]字符串。

2 个答案:

答案 0 :(得分:1)

仅当通道关闭时,通道上的public class SecondImplementation : FirstImplementation { public SecondImplementation(param1, param2, param3) : base(param1, param2) { } public override Bar Foo() { // do something with param1, param2 and param3, perhaps by calling base.Foo(). } } 语句才会退出(好吧,想一想:range将如何检测到没有其他数据要提取?),并且没有任何东西可以关闭通道通道中的代码。

答案 1 :(得分:-2)

func responseHandler(w http.ResponseWriter, r *http.Request) {
   ...
   for range c {
    sum = append(sum, <-c)
    if len(aa) == 100 {
        close(c)
   }
    fmt.Fprintln(w, sum)
}

func parse(...){
     ...
     aa = append(aa, num)
}

添加此类检查可以使您正确退出循环