golang从同一个频道读写

时间:2017-05-05 04:26:17

标签: go channel

问题代码是:

go func() {
    defer wg.Done()
    for {
        task := <-tasks

        if task.Attemts >= .5 {
            tasks <- task # <- error
        }

        Println(task)
    }
}()

在另一个循环中填充tasks <- Task{"1", rand.Float64()}的任务。

现在我们已陷入僵局......

完整示例:https://play.golang.org/p/s1pnb1Mu_Y

我的代码的重点是 - 创建web scrapper,失败后会尝试解析url。尝试一些然后丢弃网址。

可能在golang我们有一些更具思想性的方法来解决这个问题,因为我不知道。

2 个答案:

答案 0 :(得分:2)

您正在使用非缓冲通道,因此当您尝试使用tasks <- task执行时,该goroutine会在那里等待其他内容在通道上读取。由于通道上没有其他内容正在读取,因此会出现僵局。

使这个特定代码工作的唯一方法是拥有一个完全专用的消费者或使用缓冲通道。即使在这里使用缓冲通道,如果缓冲区在您的单个消费者尝试发送的位置填满,也可能会出现死锁。

如果你真的需要从同一个goroutine发送,你将不得不产生一个新的goroutine只是为了发送它。

的内容
go func() {
    tasks <- task
}()

或者你可以这样:

requeue = make(chan Task) // could buffer if you want
go func() {
    for {
        tasks <- requeue
    }
}()
for {
    task := <-tasks

    if task.Attemts >= .5 {
        requeue <- task
    }

    Println(task)
}

当然,处理该频道的关闭等。

答案 1 :(得分:0)

如果这是从频道中唯一的goroutine读取,它也不能写入它。

如果您使用缓冲频道,它可能会排序一点点工作,但这只能解决您的问题。您真正想做的事情可能是使用

go func(){
   tasks <- task
}()

而不是简单的tasks <- task。这会将写作转移到另一个goroutine,所以这个可以直接回读。