任何更好的方式来跟踪goroutine的回应?

问题描述:

我试图让我的头围绕goroutines。我创建了一个简单的程序,可以跨多个搜索引擎并行执行相同的搜索。为了跟踪答复的数量,我计算了我收到的电话号码。虽然这似乎有点业余。任何更好的方式来跟踪goroutine的回应?

当我从下面的代码中收到所有goroutine的响应时,是否有更好的方式知道?

package main 

import (
    "fmt" 
    "net/http" 
    "log" 
) 

type Query struct { 
    url string 
    status string 
} 

func search (url string, out chan Query) { 
    fmt.Printf("Fetching URL %s\n", url) 
    resp, err := http.Get(url) 

    if err != nil { 
     log.Fatal(err) 
    } 

    defer resp.Body.Close() 

    out <- Query{url, resp.Status} 
} 

func main() { 
    searchTerm := "carrot" 

    fmt.Println("Hello world! Searching for ", searchTerm) 

    searchEngines := []string{ 
     "http://www.bing.co.uk/?q=", 
     "http://www.google.co.uk/?q=", 
     "http://www.yahoo.co.uk/?q="} 

    out := make(chan Query) 

    for i := 0; i < len(searchEngines); i++ { 
     go search(searchEngines[i] + searchTerm, out) 
    } 

    progress := 0 

    for { 
        // is there a better way of doing this step? 
     if progress >= len(searchEngines) { 
      break 
     } 
     fmt.Println("Polling...") 
     query := <-out 
     fmt.Printf("Status from %s was %s\n", query.url, query.status) 
     progress++ 
    } 
} 
+1

为例,用户可以简化环路二号位,混帐摆脱进度变量,做同样的事情,第一个for循环:'for i:= 0;我 monoxygen 2013-02-23 09:16:13

+0

噢,谢谢。出于某种原因,我不感谢它的工作。 – 2013-02-23 09:31:20

+0

你也可以倒数到零而不是数起来。在等待一组goroutines完成时,这对我来说似乎更加自然。这与滚动你自己的等待组无异,并且很容易理解(在我看来,根本不是'业余')。 – 2013-02-24 08:58:04

请使用sync.WaitGroup,有在pkg doc

searchEngines := []string{ 
    "http://www.bing.co.uk/?q=", 
    "http://www.google.co.uk/?q=", 
    "http://www.yahoo.co.uk/?q="} 
var wg sync.WaitGroup 
out := make(chan Query) 

for i := 0; i < len(searchEngines); i++ { 
    wg.Add(1) 
    go func (url string) { 
     defer wg.Done() 
     fmt.Printf("Fetching URL %s\n", url) 
     resp, err := http.Get(url) 

     if err != nil { 
      log.Fatal(err) 
     } 

     defer resp.Body.Close() 

     out <- Query{url, resp.Status} 

    }(searchEngines[i] + searchTerm) 

} 
wg.Wait() 
+0

谢谢,这正是我所期待的。 – 2013-02-23 10:19:47

+2

我并不确定可能会有潜在的种族,但我仍然会在呼叫go的呼叫之前加上'wg.Add(1)',以产生一个goroutine。 – kostix 2013-02-23 11:45:01

+1

是的,你说得对,'wg.Add(1)'应该在goroutine前面,谢谢。我已经更新了代码。 – Joe 2013-02-23 12:09:59