带指针变量的Go通道和Go例程所有GOroutine都处于休眠状态-死锁
我花了一晚上的时间研究如何修复这个错误,但我没有成功。当我运行程序时,我有以下错误:“所有goroutines都处于休眠状态-死锁!”。我理解这是因为主程序在例程有可能执行其任务之前退出,我认为使用sync.WaitGroup会有所帮助,但实际上并非如此:/ 我想设置一些例程并使用通道发送URL,以便检查http状态代码。我想限制网站的并发调用数量。我已经在下面的例子中使用string而不是struct做了同样的事情,而且效果很好 任何帮助都将不胜感激:)带指针变量的Go通道和Go例程所有GOroutine都处于休眠状态-死锁,go,Go,我花了一晚上的时间研究如何修复这个错误,但我没有成功。当我运行程序时,我有以下错误:“所有goroutines都处于休眠状态-死锁!”。我理解这是因为主程序在例程有可能执行其任务之前退出,我认为使用sync.WaitGroup会有所帮助,但实际上并非如此:/ 我想设置一些例程并使用通道发送URL,以便检查http状态代码。我想限制网站的并发调用数量。我已经在下面的例子中使用string而不是struct做了同样的事情,而且效果很好 任何帮助都将不胜感激:) 主程序包 进口( “fmt” “同步”
主程序包
进口(
“fmt”
“同步”
“时间”
)
常数(
numPollers=2//要启动的轮询器goroutine数
)
var url=[]字符串{
"http://www.google.com/",
"http://golang.org/",
"http://blog.golang.org/",
"http://golangtutorials.blogspot.fr",
"https://gobyexample.com/",
}
//资源表示此程序要轮询的HTTP URL。
类型资源结构{
url字符串
}
func Poller(在中,您忘记关闭频道,等待组太长。这对我有效:您忘记关闭频道,等待组太长。这对我有效:首先,您对wg.Add()的调用太多
。对于正在运行的每个goroutine,您都会调用一次。请参阅。其次,您在完成对频道的写入后没有关闭该频道。下面是您的代码的修改版本:
package main
import (
"fmt"
"sync"
"time"
)
const (
numPollers = 2 // number of Poller goroutines to launch
)
var urls = []string{
"http://www.google.com/",
"http://golang.org/",
"http://blog.golang.org/",
"http://golangtutorials.blogspot.fr",
"https://gobyexample.com/",
}
// Resource represents an HTTP URL to be polled by this program.
type Resource struct {
url string
}
func Poller(in <-chan *Resource, wg *sync.WaitGroup) {
defer wg.Done()
for r := range in {
fmt.Printf("Finished: %v - %v\n", r.url, time.Now())
}
}
func main() {
var wg sync.WaitGroup
pending := make(chan *Resource)
wg.Add(2)
go Poller(pending, &wg)
go func() {
defer close(pending)
defer wg.Done()
for _, url := range urls {
fmt.Println("SENT > Pending url " + url)
pending <- &Resource{url: url}
}
}()
wg.Wait()
fmt.Printf("Finished all goroutines: %v\n", time.Now())
}
主程序包
进口(
“fmt”
“同步”
“时间”
)
常数(
numPollers=2//要启动的轮询器goroutine数
)
var url=[]字符串{
"http://www.google.com/",
"http://golang.org/",
"http://blog.golang.org/",
"http://golangtutorials.blogspot.fr",
"https://gobyexample.com/",
}
//资源表示此程序要轮询的HTTP URL。
类型资源结构{
url字符串
}
func Poller(在中,首先,您对wg.Add()
的调用太多。对于正在运行的每个goroutine,您都会调用一次。请参阅。其次,您在完成对频道的写入后没有关闭频道。下面是您的代码的修改版本:
package main
import (
"fmt"
"sync"
"time"
)
const (
numPollers = 2 // number of Poller goroutines to launch
)
var urls = []string{
"http://www.google.com/",
"http://golang.org/",
"http://blog.golang.org/",
"http://golangtutorials.blogspot.fr",
"https://gobyexample.com/",
}
// Resource represents an HTTP URL to be polled by this program.
type Resource struct {
url string
}
func Poller(in <-chan *Resource, wg *sync.WaitGroup) {
defer wg.Done()
for r := range in {
fmt.Printf("Finished: %v - %v\n", r.url, time.Now())
}
}
func main() {
var wg sync.WaitGroup
pending := make(chan *Resource)
wg.Add(2)
go Poller(pending, &wg)
go func() {
defer close(pending)
defer wg.Done()
for _, url := range urls {
fmt.Println("SENT > Pending url " + url)
pending <- &Resource{url: url}
}
}()
wg.Wait()
fmt.Printf("Finished all goroutines: %v\n", time.Now())
}
主程序包
进口(
“fmt”
“同步”
“时间”
)
常数(
numPollers=2//要启动的轮询器goroutine数
)
var url=[]字符串{
"http://www.google.com/",
"http://golang.org/",
"http://blog.golang.org/",
"http://golangtutorials.blogspot.fr",
"https://gobyexample.com/",
}
//资源表示此程序要轮询的HTTP URL。
类型资源结构{
url字符串
}
func Poller(在另一种情况下,对wg.Done()使用defer。例如,defer func(){wg.Done()}而不是使用两个延迟行,最好使用一个函数。defer func(){close(pending);wg.Done()}。像这样的,嗯,我喜欢遵循Go的标准libs编写代码的方式,我没有看到有多个延迟语句的代码块。至于技术方面,我不确定它可能会或可能不会影响代码。嗯,at的示例使用多个延迟语句,尽管这是一个不同的用例。除此之外,我不知道ink我已经看到了一个官方的例子。谢谢你的回答,我没有走那么远!第二个wg.Add(1)在迭代URL片段时是一次尝试,我在这里发布时忘了删除,我知道它不需要。我不明白为什么我应该运行“defer wg.Done()在程序中有两次,它在轮询器函数中有意义,但在主函数中没有意义?另外,对wg.Done()使用defer。例如,defer func(){wg.Done()}而不是使用两个defer行,最好使用一个函数。defer func(){close(pending);wg.Done()}。像这样的,嗯,我喜欢遵循Go的标准libs编写代码的方式,我没有看到有多个延迟语句的代码块。至于技术方面,我不确定它可能会或可能不会影响代码。嗯,at的示例使用多个延迟语句,尽管这是一个不同的用例。除此之外,我不知道ink我已经看到了一个官方的例子。谢谢你的回答,我没有走那么远!第二个wg.Add(1)在迭代URL片段时是一次尝试,我在这里发布时忘了删除,我知道它不需要。我不明白为什么我应该运行“defer wg.Done()在程序中有两次,它在轮询器函数中有意义,但在主函数中没有意义?将来,当您遇到阻塞问题时,您可以向进程发送一个SIGQUIT
,以打印堆栈跟踪,该跟踪将显示所有goroutine正在等待的位置。将来当您遇到阻塞问题时,您可以向进程发送一个SIGQUIT
>打印堆栈跟踪,该跟踪将显示所有goroutine等待的位置。