作为第一个项目,我决定编写一个简单的异步网络浏览器。我的想法是要有一个任务队列和一组“解决”任务的工人。在编写程序时遇到了一个问题。
以下代码挂起:
<div onmouseover="writeText2('the div works fine')">
MOUSE OVER DIV
</div>
<td>
<p id="text_field2">
Prefer this to stay as default text if user moves mouse off the td above
</p>
</td>
<td onmouseover="writeText2('the td works fine')">
MOUSE OVER TD
</td>
而事实并非如此:
package main
import (
"fmt"
"net/http"
"time"
)
type Scraper struct {
client http.Client
timeout int
tasks chan string
results chan int
ntasks int
}
func (s Scraper) Init(timeout int, workers int) {
s.client = http.Client{
Timeout: time.Second * time.Duration(timeout),
}
s.timeout = timeout
s.ntasks = 0
s.Dispatch(workers)
}
func (s Scraper) Wait() {
for i := 0; i < s.ntasks; i++ {
<-s.results
}
}
func (s Scraper) Task(task string) {
s.tasks <- task // hangs on this line
s.ntasks++;
}
func (s Scraper) Dispatch(workers int) {
s.tasks = make(chan string, 100)
s.results = make(chan int, 100)
for i := 0; i < workers; i++ {
go s.worker(i)
}
}
func (s Scraper) worker(id int) {
for task := range <-s.tasks {
fmt.Println(task)
s.results <- 0
}
}
func main() {
s := Scraper{}
s.Init(10, 5)
s.Task("Hello World")
s.Wait()
}
看着堆栈溢出,我看到未缓冲的通道挂起,但是make(chan string,100)应该创建一个缓冲的通道。
答案 0 :(得分:0)
将所有接收者更改为指针,如下所示:
func (s *Scraper) Init(timeout int, workers int) // *Scraper not 'Scraper'
有关指针接收器的更多详细信息:https://tour.golang.org/methods/4
@JimB指出-范围也有错误,应该像这样:
func (s *Scraper) worker(id int) {
// `range s.tasks` not `range <-s.tasks`
for task := range s.tasks {
fmt.Println(task)
s.results <- 0
}
}
带有接收器和范围修正的游乐场:https://play.golang.org/p/RulKHHfnvJo