Her ne kadar sync.waitGroup
(wg) kanonik yolu ileriye, bu sizin en azından birkaçını yapmak gerektirir wg.Add
senden önce aramalar wg.Wait
tamamlandı herkes için. Bu, özyinelemeli aramaların sayısını önceden bilmediğiniz ve aramaları yönlendiren verileri almanın biraz zaman aldığı bir web gezgini gibi basit şeyler için uygun olmayabilir wg.Add
. Sonuçta, ilk alt sayfa grubunun boyutunu bilmeden önce ilk sayfayı yüklemeniz ve ayrıştırmanız gerekir.
Ben kaçınarak kanallarını kullanarak bir çözüm yazdım waitGroup
benim çözümde web gezgini - Go Tur egzersiz. Bir veya daha fazla go-rutin başlatıldığında, numarayı children
kanala gönderirsiniz . Bir geçiş rutini tamamlamak üzere olduğu her seferinde 1
, done
kanala bir gönderirsiniz . Çocukların toplamı yapılanların toplamına eşit olduğunda, bitmiş oluruz.
Geriye kalan tek endişem, results
kanalın kodlanmış boyutu , ancak bu (mevcut) bir Go sınırlaması.
// recursionController is a data structure with three channels to control our Crawl recursion.
// Tried to use sync.waitGroup in a previous version, but I was unhappy with the mandatory sleep.
// The idea is to have three channels, counting the outstanding calls (children), completed calls
// (done) and results (results). Once outstanding calls == completed calls we are done (if you are
// sufficiently careful to signal any new children before closing your current one, as you may be the last one).
//
type recursionController struct {
results chan string
children chan int
done chan int
}
// instead of instantiating one instance, as we did above, use a more idiomatic Go solution
func NewRecursionController() recursionController {
// we buffer results to 1000, so we cannot crawl more pages than that.
return recursionController{make(chan string, 1000), make(chan int), make(chan int)}
}
// recursionController.Add: convenience function to add children to controller (similar to waitGroup)
func (rc recursionController) Add(children int) {
rc.children <- children
}
// recursionController.Done: convenience function to remove a child from controller (similar to waitGroup)
func (rc recursionController) Done() {
rc.done <- 1
}
// recursionController.Wait will wait until all children are done
func (rc recursionController) Wait() {
fmt.Println("Controller waiting...")
var children, done int
for {
select {
case childrenDelta := <-rc.children:
children += childrenDelta
// fmt.Printf("children found %v total %v\n", childrenDelta, children)
case <-rc.done:
done += 1
// fmt.Println("done found", done)
default:
if done > 0 && children == done {
fmt.Printf("Controller exiting, done = %v, children = %v\n", done, children)
close(rc.results)
return
}
}
}
}
Çözüm için tam kaynak kodu