我来自 Node.js 背景,在那里做一些异步工作非常容易,然后在完成长时间运行的任务后做更多的工作,我确信它在 Go 中是一样的,但我只是没有'我还没有完全了解 channel 的运作方式。
我正在为我玩的一个老游戏构建一个解析器,它分析拍卖数据日志中的行并解析它们以通过套接字 io 流式传输到网站上的实时提要。一个文件一次可以发送 100 行,我的解析器必须一次分析每一行并从每一行中提取元信息(例如商品、商品价格等)
每一行都有这个 for 循环针对它运行(这假设项目列表的部分是从正则表达式派生的):
itemChannel := make(chan Item)
for _, itemName := range itemList {
item := Item {
Name: itemName,
}
// Long running method which does parsing for the item such as pricing, quantity and makes some http calls (runs 75ms on average)
go item.FetchData(itemChannel)
// Read from the channel when its done
raw := <-itemChannel
auction.Items = append(auction.Items, raw)
auction.Seller = seller
}
auctions = append(auctions, auction)
fmt.Println("Appended auction: ", auction)
go c.publishToRelayService(auction)
现在(根据观察)好像raw := <-itemChannel
导致循环阻塞,直到 goroutine 完成并将其数据传回(这肯定意味着以 item.FetchData(itemChannel)
运行会做同样的事情。当数据返回到 channel 中时,我如何从 channel 中读取数据,但跳出循环迭代作为尽可能快。有些行中有 15-20 个项目,这导致程序在解析下一行之前暂停约 2-3 秒。我希望能够比那更快地中断并处理下一行使解析器尽可能快。是否有任何类似于 Node 中的 Promises 的机制,我可以在其中将完成处理程序链接到 item.FetchData()
的每个完成?
注意 fetchChannel
当所有获取工作完成后,将写入我的 Item 类型内部。
最佳答案
您可以编写一个不同的 go 例程来等待 channel 中的新数据并对其进行处理。 这样生产者和消费者并行运行,当生产者完成生产消费者时必须完成,因为这里消费者是一个轻进程
您可以使用done
channel 来指示消费者已完成
这里是你可以如何修改代码
itemChannel := make(chan Item)
done := make(chan bool)
//Consumer
go func(channel chan Item) {
for raw := range channel {
auction.Items = append(auction.Items, raw)
auction.Seller = seller
auctions = append(auctions, auction)
}
done <- true
}(itemChannel)
//Producer
for _, itemName := range itemList {
item := Item{
Name: itemName,
}
// Long running method which does parsing for the item such as pricing, quantity and makes some http calls (runs 75ms on average)
go item.FetchData(itemChannel)
}
<-done
fmt.Println("Appended auction: ", auction)
go c.publishToRelayService(auction)
关于go - 我在 golang 中错误地使用了 channel 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41754198/