go - Goroutines blocked by for loop? -
i have following code implements worker queue:
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() { { 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) := 0; < numscrapers; i++ { s := initscraper(i+1, scraperqueue) s.start() } go func() { { select { case link := <-linkqueue: go func() { scraper := <-scraperqueue scraper <- link }() } } }() cycledirectory(1) // time.sleep(1 * time.millisecond) { // select { // } } // http.handlefunc("/hello", helloserver) // http.listenandserve(":12345", nil) }
running code using loop containing if statement (or nothing inside), scraper not print received message. blocking using listenandserve function net/http, prints received message. blocking using sleep 1 ms, receive message. , putting select statement in loop, receive message.
why loop without select statement not allowing execution of message sending in worker queues, , how go handling this. need if statement in loop check if work has been done can exit loop , end program.
update
amd's suggestion solution problem. here updated code using sync.waitgroup package main
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() { { 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) := 0; < numscrapers; i++ { s := initscraper(i+1, scraperqueue) s.start() } go func() { { select { case link := <-linkqueue: go func() { scraper := <-scraperqueue scraper <- link }() } } }() cycledirectory(1) wg.wait() fmt.println("done") }
you may use sync.waitgroup
stop program exiting until work done.
try on 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.") }
Comments
Post a Comment