gpt4 book ai didi

Goroutines被for循环阻塞?

转载 作者:数据小太阳 更新时间:2023-10-29 03:26:36 26 4
gpt4 key购买 nike

我有以下实现工作队列的代码:

package main

import (
"fmt"
"net/http"
"io"
"time"
)

var (
linkQueue chan Link
scraperQueue chan chan Link
)

func CycleDirectory(page int) {
linkQueue <- Link{Name: "asd"}
}

type Link struct {
Name string
}

func (s Scraper) Start() {
fmt.Println("Started")
go func() {
for {
s.ScraperQueue <- s.Link
select {
case link := <-s.Link:
fmt.Println(fmt.Sprintf("%v", s.Id) + ": Received " + link.Name)
case <-s.QuitChan:
fmt.Println("Closed")
return
}
}
}()
}

func (s Scraper) Stop() {
go func() {
s.QuitChan <- true
}()
}

type Scraper struct {
Id int
Link chan Link
ScraperQueue chan chan Link
QuitChan chan bool
}

func InitScraper(id int, scraperQueue chan chan Link) Scraper {
return Scraper {
Id: id,
Link: make(chan Link),
ScraperQueue: scraperQueue,
QuitChan: make(chan bool),
}
}

func HelloServer(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "hello, world!\n")
}

func main() {
linkQueue = make(chan Link, 2000)

numScrapers := 2

scraperQueue = make(chan chan Link, numScrapers)

for i := 0; i < numScrapers; i++ {
s := InitScraper(i+1, scraperQueue)
s.Start()
}

go func() {
for {
select {
case link := <-linkQueue:
go func() {
scraper := <-scraperQueue
scraper <- link
}()
}
}
}()

CycleDirectory(1)

// time.Sleep(1 * time.Millisecond)

for {
// select {
// }
}

// http.HandleFunc("/hello", HelloServer)

// http.ListenAndServe(":12345", nil)
}

使用包含 if 语句(或内部没有任何内容)的 for 循环运行此代码,爬虫不会打印收到的消息。使用来自 net/http 的 ListenAndServe 函数进行阻塞,它打印接收到的消息。使用 sleep 阻塞 1 毫秒,我收到消息。在 for 循环中放置一个 select 语句,我也收到了消息。

为什么没有 select 语句的 for 循环不允许执行在工作队列中发送的消息,我将如何处理这个问题。我需要 for 循环中的 if 语句来检查是否所有工作都已完成,以便我可以退出循环并结束程序。

更新

Amd 的建议是解决这个问题的方法。这是我使用 sync.WaitGroup 更新的代码 包主

import (
"fmt"
"sync"
)

var (
linkQueue chan Link
scraperQueue chan chan Link
wg sync.WaitGroup
)

func CycleDirectory(page int) {
wg.Add(1)
linkQueue <- Link{Name: "asd"}
}

type Link struct {
Name string
}

func (s Scraper) Start() {
fmt.Println("Started")
go func() {
for {
s.ScraperQueue <- s.Link
select {
case link := <-s.Link:
Scrape(s.Id, link.Name)
s.Stop()
case <-s.QuitChan:
fmt.Println("Closed")
wg.Done()
return
}
}
}()
}

func (s Scraper) Stop() {
go func() {
s.QuitChan <- true
}()
}

type Scraper struct {
Id int
Link chan Link
ScraperQueue chan chan Link
QuitChan chan bool
}

func Scrape(id int, name string) {
fmt.Println(fmt.Sprintf("%v", id) + ": Received " + name)
}

func InitScraper(id int, scraperQueue chan chan Link) Scraper {
return Scraper {
Id: id,
Link: make(chan Link),
ScraperQueue: scraperQueue,
QuitChan: make(chan bool),
}
}

func main() {
linkQueue = make(chan Link, 2000)

numScrapers := 2

scraperQueue = make(chan chan Link, numScrapers)

for i := 0; i < numScrapers; i++ {
s := InitScraper(i+1, scraperQueue)
s.Start()
}

go func() {
for {
select {
case link := <-linkQueue:
go func() {
scraper := <-scraperQueue
scraper <- link
}()
}
}
}()

CycleDirectory(1)

wg.Wait()

fmt.Println("Done")
}

最佳答案

您可以使用sync.WaitGroup 来阻止程序退出,直到所有工作完成。
试试 The Go Playground :

package main

import (
"fmt"
"sync"
"time"
)

var (
wg sync.WaitGroup
)

func main() {
wg.Add(1)
go func() {
defer wg.Done()
time.Sleep(2 * time.Second)
}()

fmt.Println("Wait...")
wg.Wait()
fmt.Println("Done.")
}

关于Goroutines被for循环阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39642189/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com