死锁问题+使用通道时goroutine数量增加

死锁问题+使用通道时goroutine数量增加,go,Go,我正在使用Go开发一个简单的http状态检查程序。这个项目一开始进展顺利。然后我将频道引入其中,它不会停止。换句话说,不会触发WorkGroup.Done 如何触发工作组。完成 //前往游乐场:https://play.golang.org/p/1AzXEAV9p4K 包干管 进口 fmt net/http 运行时 同步 类型urlState结构{ url字符串 州议会 } func checklink string,c chan程序会为v:=范围c而阻塞,因为通道上的范围会一直持续到通道关闭。

我正在使用Go开发一个简单的http状态检查程序。这个项目一开始进展顺利。然后我将频道引入其中,它不会停止。换句话说,不会触发WorkGroup.Done

如何触发工作组。完成

//前往游乐场:https://play.golang.org/p/1AzXEAV9p4K 包干管 进口 fmt net/http 运行时 同步 类型urlState结构{ url字符串 州议会 } func checklink string,c chan程序会为v:=范围c而阻塞,因为通道上的范围会一直持续到通道关闭。通过接收预期数量的值进行修复。此更改不需要WaitGroup

result := true
stats := make(map[string]bool)
fmt.Println(`total sites: `, len(links))

c := make(chan urlState, len(links))
for _, link := range links {
    stats[link] = false
    fmt.Println(`requesting...`, link)
    go checkLink(link, c)
    fmt.Println(`goroutines: `, runtime.NumGoroutine())
}

for i := 0; i < len(links); i++ {
    v := <-c
    fmt.Println(`recv from channel, assigning result for `, v.url)
    stats[v.url] = v.state
    fmt.Println(`goroutines: `, runtime.NumGoroutine())
}

fmt.Println(`work finished!`)
for key, value := range stats {
    fmt.Println(key, `---`, value)
    if value == false {
        result = false
    }
}

你正在处理多少个链接?我不认为有任何理由它永远不会完成,但你已经有效地告诉它同时处理所有链接。如果有足够多的链接,这将是一个有效的分叉炸弹,而且您在启动goroutines时会消耗大量内存,因此它可能永远不会完成。如果有足够的内存和时间,它应该在逻辑上完成。您可能需要的是一次限制10、50或100个链接。@Flimzy这是一个有效点。当我使用不同的编程语言开发网络爬虫时,我遇到过类似的情况。然而,我写这段代码是为了适应围棋。即使只有一个链接,代码仍然没有完成。goplayder:
func checkLink(link string, c chan<- urlState, wg *sync.WaitGroup) {
    defer wg.Done()
    ... remainder of function is same as before
}

func Check(links []string) bool {
    result := true
    stats := make(map[string]bool)
    var wg sync.WaitGroup
    fmt.Println(`total sites: `, len(links))
    wg.Add(len(links)) // add workgroups of exactly same amount as links array length

    c := make(chan urlState, len(links))
    for _, link := range links {
        stats[link] = false
        fmt.Println(`requesting...`, link)
        go checkLink(link, c, &wg)
        fmt.Println(`goroutines: `, runtime.NumGoroutine())
    }

    // Close c when checkLink goroutines complete.
    go func() {
        wg.Wait()
        close(c)
    }()

    for v := range c {
        fmt.Println(`recv from channel, assigning result for `, v.url)
        stats[v.url] = v.state
        wg.Done()
        fmt.Println(`goroutines: `, runtime.NumGoroutine())
    }

    fmt.Println(`work finished!`)
    for key, value := range stats {
        fmt.Println(key, `---`, value)
        if value == false {
            result = false
        }
    }
    return result
}