首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >递归的Goroutines,告诉Go停止从频道阅读的最简洁的方法是什么?

递归的Goroutines,告诉Go停止从频道阅读的最简洁的方法是什么?
EN

Stack Overflow用户
提问于 2014-11-24 10:55:04
回答 3查看 8.2K关注 0票数 16

我想知道解决这个问题的惯用方法(目前这会引发死锁错误),递归分支的次数未知,所以我不能简单地关闭通道。

_

我传递了一个指向一个数字的指针,并对其进行了递增,从而使它正常工作,我还研究了使用Sync等待组的问题。我没有感觉到(也许我错了),我想出了一个优雅的解决方案。我见过的围棋例子往往简单、聪明、简洁。

这是Go巡回赛的最后一次练习,https://tour.golang.org/#73

你知道“围棋程序员”会如何处理这个问题吗?任何帮助都将不胜感激。我正努力从一开始就好好学习。

EN

Stack Overflow用户

发布于 2019-01-04 10:04:34

这是我如何解决网络爬虫练习的围棋

用于跟踪并行执行中的递归完成,我使用了原子整数计数器来跟踪有多少urls在并行递归中被爬行。在主函数中,我在循环中等待,直到原子计数器减少到零。

为了避免再次抓取相同的,我使用了一个带有Mutex的地图来跟踪爬行的URL。

下面是相同的代码片段。

你可以找到在Github上的整个工作代码

代码语言:javascript
复制
// Safe HashSet Version
type SafeHashSet struct {
    sync.Mutex
    urls map[string]bool //Primarily we wanted use this as an hashset, so the value of map is not significant to us
}

var (
    urlSet     SafeHashSet
    urlCounter int64
)

// Adds an URL to the Set, returns true if new url was added (if not present already)
func (m *SafeHashSet) add(newUrl string) bool {
    m.Lock()
    defer m.Unlock()
    _, ok := m.urls[newUrl]
    if !ok {
        m.urls[newUrl] = true
        return true
    }
    return false
}


// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher) {

    // Decrement the atomic url counter, when this crawl function exits
    defer atomic.AddInt64(&urlCounter, -1)

    if depth <= 0 {
        return
    }

    // Don't Process a url if it is already processed
    isNewUrl := urlSet.add(url)

    if !isNewUrl {
        fmt.Printf("skip: \t%s\n", url)
        return
    }


    body, urls, err := fetcher.Fetch(url)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("found: \t%s %q\n", url, body)

    for _, u := range urls {
        atomic.AddInt64(&urlCounter, 1)
        // Crawl parallely
        go Crawl(u, depth-1, fetcher)
    }
    return
}

func main() {
    urlSet = SafeHashSet{urls: make(map[string]bool)}

    atomic.AddInt64(&urlCounter, 1)
    go Crawl("https://golang.org/", 4, fetcher)

    for atomic.LoadInt64(&urlCounter) > 0 {
        time.Sleep(100 * time.Microsecond)
    }
    fmt.Println("Exiting")
}
票数 0
EN
查看全部 3 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27103161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档