可能这是当从未处理过多线程的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失败(。<<<<<<<<<<<<<<<<<</p>
tldr:您的循环正在等待您的功能退出,并且您的功能正在等待您的循环退出 - 僵局