了解Golang频道.所有的goroutines都睡着了 - 僵局[GO Tour,Crawler]



可能这是当从未处理过多线程的PHP开发者开始学习Golang和频道时会发生这种情况。

我正在上次练习GO,[练习:Web crawler](在此之前我没有其他练习的问题(

我试图编写尽可能简单的代码,我的爬网方法看起来像:

func Crawl(url string, depth int, fetcher Fetcher) {
    // kick off crawling by passing initial Url to a Job queue
    Queue <- Job{
        url,
        depth,
    }
    // make sure we close the Queue channel
    defer close(Queue)
    // read from the Queue
    for job := range Queue {
        // if fetched or has hit the bottom of depth,
        // just continue right away to pick up next Job
        if fetched.Has(job.Url) || job.Depth <= 0 {
            continue
        }
        fres := fetcher.Fetch(job.Url)
        fetched.Add(job.Url, fres)
        for i := range fres.Urls {
            // send new urls just fetched from current url in Job
            // to the Queue
            Queue <- Job{
                fres.Urls[i], job.Depth - 1,
            }
        }
    }
    for _, res := range fetched.m {
        fmt.Println(res)
    }
}

go run说我不应该写任何go代码,然后返回PHP

fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.Crawl(0xf37c1, 0x12, 0x4, 0x1600e0, 0x104401c0, 0x104000f0)
    /tmp/sandbox452918312/main.go:64 +0x80
main.main()
    /tmp/sandbox452918312/main.go:87 +0x60

当然,我已经搜索了这个问题,结论通常是:"关闭你的chans",我做了(我是吗?(。

那么,有人可以指出我在这里缺少什么?

完整的代码在这里:https://play.golang.org/p/-98sdvndd6

这项练习最惯用的golang方法是什么?我找到了少数。

  • avalanche123
  • fgrehm
  • https://play.golang.org/p/zovub8kdl-

等。哪一个似乎是您的干净解决方案?

另外,我应该使用channels 与goroutines?

您是'推迟队列的关闭。这意味着"当此功能(爬网(退出时关闭队列!"

然后,您输入将阻止它的循环:

  1. 收到项目或
  2. "队列"已关闭

开始时队列中添加了一个"作业"(这将允许循环运行一次(,然后在第一次运行结束时,循环将阻塞直到上述两个条件中的任何一个都再次见面。

注意:通过第一个循环的运行可能会在队列中添加更多项目(因此引起更多迭代(,但是在某个时候,循环的队列将耗尽,循环将再次阻止等待以上两个条件之一

但是,排队中再也不会添加任何项目(因此#1失败(,并且"队列"仅在此功能退出后才关闭,直到循环退出后才能发生(因此#2失败(。<<<<<<<<<<<<<<<<<</p>

tldr:您的循环正在等待您的功能退出,并且您的功能正在等待您的循环退出 - 僵局

最新更新