带指针变量的Go通道和Go例程所有GOroutine都处于休眠状态-死锁

带指针变量的Go通道和Go例程所有GOroutine都处于休眠状态-死锁,go,Go,我花了一晚上的时间研究如何修复这个错误,但我没有成功。当我运行程序时,我有以下错误:“所有goroutines都处于休眠状态-死锁!”。我理解这是因为主程序在例程有可能执行其任务之前退出,我认为使用sync.WaitGroup会有所帮助,但实际上并非如此:/ 我想设置一些例程并使用通道发送URL,以便检查http状态代码。我想限制网站的并发调用数量。我已经在下面的例子中使用string而不是struct做了同样的事情,而且效果很好 任何帮助都将不胜感激:) 主程序包 进口( “fmt” “同步”

我花了一晚上的时间研究如何修复这个错误,但我没有成功。当我运行程序时,我有以下错误:“所有goroutines都处于休眠状态-死锁!”。我理解这是因为主程序在例程有可能执行其任务之前退出,我认为使用sync.WaitGroup会有所帮助,但实际上并非如此:/

我想设置一些例程并使用通道发送URL,以便检查http状态代码。我想限制网站的并发调用数量。我已经在下面的例子中使用string而不是struct做了同样的事情,而且效果很好

任何帮助都将不胜感激:)

主程序包
进口(
“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等待的位置。