2012-09-01 100 views
4

我一直在去巡迴演出,我已經完成了網絡爬蟲練習,但我認爲我用來打印所有結果的技術可能效率低下。如何打印來自併發和遞歸函數的結果?

這是我的代碼。我只編輯抓取和主要功能,所以我只是發佈。這裏是給鍛鍊(http://tour.golang.org/#70

var used = make(map[string]bool) 

    func Crawl(url string, depth int, fetcher Fetcher, results chan string) { 
     if depth <= 0 { 
      return 
     } 
     body, urls, err := fetcher.Fetch(url) 
     if err != nil { 
      results <- fmt.Sprintf("%v",err) 
      return 
     } 
     results <-fmt.Sprintf("\nfound: %s %q\n", url, body) 
     for _,u := range urls { 
      if used[u] == false { 
       used[u] = true 
       go Crawl(u, depth-1, fetcher, results) 
      } 
     } 
     return 
    } 
    //------------------------------------------------------------ 
    func main() { 
     used["http://golang.org/"] = true 
     results := make(chan string) 
     go Crawl("http://golang.org/", 4, fetcher, results) 
     for i := 0; i < len(used); i++ { 
      fmt.Println(<-results) 
     } 
    } 

鏈路我使用了「對於i < LEN(使用)」行中主要以確保如果有一個結果來打印從結果值僅打印。我不能只用

for i := range results 

,因爲它是很難用「關閉(結果)」中的爬取功能,因爲它是遞歸的,但我做到這一點我必須要找到變量的長度每次都使用。

有沒有更好的方法來做到這一點?

回答

2

要等待一系列goroutines完成,請使用sync.WaitGroup。

我相信你會找到官方文檔非常熟悉的例子..

http://golang.org/pkg/sync/#example_WaitGroup

報價:

var wg sync.WaitGroup 
var urls = []string{ 
    "http://www.golang.org/", 
    "http://www.google.com/", 
    "http://www.somestupidname.com/", 
} 
for _, url := range urls { 
    // Increment the WaitGroup counter. 
    wg.Add(1) 
    // Launch a goroutine to fetch the URL. 
    go func(url string) { 
     // Fetch the URL. 
     http.Get(url) 
     // Decrement the counter. 
     wg.Done() 
    }(url) 
} 
// Wait for all HTTP fetches to complete. 
wg.Wait() 

這將阻止,直到所有的工作就完成了。

如果您真的想在收集結果時逐步打印結果,最簡單的方法就是在收集器本身中完成它。