2017-09-24 1 views
0

'A Tour of Go'の例で言及したように、クロール機能を変更して、 1つのURLだけが印刷されたので、別のスレッドを生成します。'Go Tour'のクロール例では無効になりました

私の変更に何か問題はありますか?あなたのプログラムで

リストとして以下の私の修正、

// Crawl uses fetcher to recursively crawl 
// pages starting with url, to a maximum of depth. 
func Crawl(url string, depth int, fetcher Fetcher) { 
    // TODO: Fetch URLs in parallel. 
    // TODO: Don't fetch the same URL twice. 
    // This implementation doesn't do either: 
    if depth <= 0 { 
     fmt.Printf("depth <= 0 return") 
     return 
    } 
    body, urls, err := fetcher.Fetch(url) 
    if err != nil { 
     fmt.Println(err) 
     return 
    } 
    fmt.Printf("found: %s %q\n", url, body) 
    crawled.mux.Lock() 
    crawled.c[url]++ 
    crawled.mux.Unlock() 
    for _, u := range urls { 
     //crawled.mux.Lock() 
     if cnt, ok := crawled.c[u]; ok { 
      cnt++ 
     } else { 
      fmt.Println("go ...", u) 
      go Crawl(u, depth-1, fetcher) 
     } 
     //crawled.mux.Unlock() 
     //Crawl(u, depth-1, fetcher) 
    } 
    return 
} 


type crawledUrl struct { 
    c map[string]int 
    mux sync.Mutex 
} 

var crawled = crawledUrl{c: make(map[string]int)} 

答えて

0

、あなたは、外出先ルーチンのための任意の同期ツールを持っていません。

このコードの動作は未定義です。 おそらく、メインのスレッドはすぐに終了します。

goルーチンの実行を同期させるために何らかの種類のutilを明示的に使用した場合にのみ、メインのgoルーチンは他のgoルーチンを終了するのをブロックしません。

チャネルまたは有用な同期ユーティリティなど。

私はバージョンを与えるのを手伝います。

type fetchState struct { 
    mu  sync.Mutex 
    fetched map[string]bool 
} 

func (f *fetchState) CheckAndMark(url string) bool { 
    defer f.mu.Unlock() 

    f.mu.Lock() 
    if f.fetched[url] { 
     return true 
    } 
    f.fetched[url] = true 
    return false 
} 

func mkFetchState() *fetchState { 
    f := &fetchState{} 
    f.fetched = make(map[string]bool) 
    return f 
} 

func CrawlConcurrentMutex(url string, fetcher Fetcher, f *fetchState) { 
    if f.CheckAndMark(url) { 
     return 
    } 

    body, urls, err := fetcher.Fetch(url) 
    if err != nil { 
     fmt.Println(err) 
     return 
    } 
    fmt.Printf("found: %s %q\n", url, body) 
    var done sync.WaitGroup 
    for _, u := range urls { 
     done.Add(1) 
     go func(u string) { 
      defer done.Done() 
      CrawlConcurrentMutex(u, fetcher, f) 
     }(u) // Without the u argument there is a race 
    } 
    done.Wait() 
    return 
} 

sync.WaitGroupの使い方に注意してください、docを参照してください、あなたは全体の話を理解することができますしてください。

関連する問題