如何在每次更新频道时启动新的goroutine



我正在制作一个监控不同网页的程序,每次向页面添加新的url时,我都想启动一个新的goroutine来抓取新的url。我试着这样模拟:

package main
import (
"fmt"
"sync"
"time"
)
func main() {
var Wg sync.WaitGroup
link := make(chan string)
startList := []string{}
go func() {
for i := 0; i < 20; i++ {
//should simulate the monitoring of the original web page
nextLink := fmt.Sprintf("cool-website-%d", i)
link <- nextLink
}
}()
for i := 0; i < 20; i++ {
newLink := <-link
startList = append(startList, newLink)
Wg.Add(1)
go simulateScraping(i, startList[i])
Wg.Done()
}
Wg.Wait()
}
func simulateScraping(i int, link string) {
fmt.Printf("Simulating process %dn", i)
fmt.Printf("scraping www.%s.comn", link)
time.Sleep(time.Duration(30) * time.Second)
fmt.Printf("Finished process %dn", i)
}

这将导致以下错误fatal error: all goroutines are asleep - deadlock!。如何只在每次更新newLink或向其添加startList时启动simulateScreating函数?

谢谢!

我发现代码有几个问题。

  1. 等待组在代码中是无用的,因为Wg.Done会立即调用,并且不会等到simulateScraping完成,因为它是并行运行的

要解决此问题,可以使用关闭功能

go func(i int) {
simulateScraping(i, newLink)
Wg.Done()
}(i)
  1. 我会对每个范围循环使用,而不是增量循环。它允许在新值到达通道时立即执行代码,并在通道关闭时自动中断
var i int
for newLink := range link {
Wg.Add(1)
go func(i int) {
simulateScraping(i, newLink)
Wg.Done()
}(i)
i++
}
Wg.Wait()
  1. startList := []string{}看起来没用。不确定它应该如何使用。

  2. 通道必须关闭。

go func() {
for i := 0; i < 20; i++ {
//should simulate the monitoring of the original web page
nextLink := fmt.Sprintf("cool-website-%d", i)
link <- nextLink
}
close(link) // Closing the channel
}()

全代码

package main
import (
"fmt"
"sync"
"time"
)
func main() {
var Wg sync.WaitGroup
link := make(chan string)
go func() {
for i := 0; i < 20; i++ {
//should simulate the monitoring of the original web page
nextLink := fmt.Sprintf("cool-website-%d", i)
link <- nextLink
}
close(link)
}()
var i int
for newLink := range link {
Wg.Add(1)
go func(i int) {
simulateScraping(i, newLink)
Wg.Done()
}(i)
i++
}
Wg.Wait()
}
func simulateScraping(i int, link string) {
fmt.Printf("Simulating process %dn", i)
fmt.Printf("scraping www.%s.comn", link)
time.Sleep(3 * time.Second)
fmt.Printf("Finished process %dn", i)
}

这里有一个关于";围棋中的并发模式;

最新更新