我有一个应用程序,它每隔几秒钟就会创建一个例程,以从API获取当前价格。然后将响应发送到Monitor例程进行分析。如果监视器发现价格已发生重大变化,它将发送通知。
如果每个执行例程之间的延迟较大,则该方法很好。如果很小,则不是这样:“致命错误:所有goroutine都在睡着-死锁!”被触发,程序崩溃。
我正在猜测(?)死锁是由于以下两种原因之一:(1)监控器被新的价格信息所淹没(并且无法及时分析它们);或(2)主功能被监视器的消息淹没。
在Monitor迭代遍历Main函数时,Main函数会将新价格附加到切片中,这可能还存在一些缺点。
如何解决?在这里阅读其他文章,我认为“选择”语句将是万灵丹,但似乎并非如此。
func main() {
ec := make(chan entry, 10)
mce := make (chan entry, 10)
mcn := make(chan string, 10)
go monitor(mce, mcn)
for {
go fetchData(ec)
select {
// get entries
case newEntry := <- ec:
log = append(log, newEntry)
mce <- newEntry
default:
{}
}
//check if any notifications received
select {
case newMsg := <- mcn:
fmt.Println(newMsg)
default:
{}
}
delay()
}
}
func monitor(mce <-chan entry, mcn chan<- string) {
for {
newEntry = <- mce
for _, item := range log {
// here - do some analysis comparing the newEntry against previous entries
// (essentially to see if notification should be triggered)
}
if should_send_notification {
mcn <- msg
}
}
}
func fetchData(ec chan<- entry) {
// here some code fetching newEntry from APIs
// send the newEntry back to the main function
ec <- newEntry
}
答案 0 :(得分:0)
您只需要合并一个select并删除main函数上的默认语句。删除默认语句后,您就不需要delay()函数,因为select-case会阻止并等待通道中的某些消息:
func main() {
ec := make(chan entry, 10)
mce := make (chan entry, 10)
mcn := make(chan string, 10)
go monitor(mce, mcn)
go fetchData(ec)
for {
select {
// get entries
case newEntry := <- ec:
log = append(log, newEntry)
mce <- newEntry
//check if any notifications received
case newMsg := <- mcn:
fmt.Println(newMsg)
}
}
}
fetchData(ec)可以方便地实现类似阻塞的操作,并且不必连续调用它:
func fetchData(ec chan<- entry) {
for {
// here some code fetching newEntry from APIs
// waiting data
// send the newEntry if I get data
ec <- newEntry
}
}