我对go func中的plain go func和for循环之间的区别有一些疑问:
Plain go Func:
func asyncTask(){
//...something
}
为了触发asyncTask,我们可以简单地说:
func main(){
go asyncTask()
}
制作一个for循环来监控频道:
func (c *Container) asyncTask(){
go func(){
for {
select {
case <- c.someChan:
//...do something
case <-c.ctx.Done():
//...prevent leaking
}
}
}()
}
触发:
func (c *Container) trigger(){
c.someChan <- val
}
我的问题是:
我理解第二种情况最适合我们希望管理队列中的异步任务的情况。 但是说出经常触发的异步任务(不能阻止)的性能,哪种方法更好?
在GoLang中处理异步任务是否有一般的最佳做法?
答案 0 :(得分:4)
几乎在任何情况下,在选择使用哪种模式时都不考虑性能(两者都很好),但在特定用例中哪些用法有意义。如果使用模式(1),则无法保证(2)的顺序处理。这是两个例子之间的本质区别。因此,对于http服务器,您可以使用前一种模式(go handleRequest(r HttpRequest)
说)并行处理请求,但使用后者确保按顺序处理某些操作。我希望这是回答你的问题!
答案 1 :(得分:1)
如果你有需要考虑的goroutines,你可以将模型#1与WaitGroups一起使用,并且只对他们的退出感到困扰,因此不需要管理等等。
当您需要明确的管理/控制/沟通时,您可以使用模型#2。通道通信不是免费的 - 发送和接收例程需要同步/通道在发送值时需要锁定,很多事情都必须在引擎盖下发生。
除非有必要,否则绝对选择#1是可行的方法。看看你的问题最简单的解决方案是什么 - 我知道这很容易传播,但简单可能需要一段时间才能实现。
答案 2 :(得分:1)
简而言之,从我所知道的情况来看,上面提到的2种模式并不能真正地比较使用哪种模式或哪种模式更好。它们都有不同的用例,具有不同的必要性。
据我所知,这不是关于
在go func中使用go go func和for循环
不同用途更多。
在回答你的问题之前,我想尝试简单解释你提到的两种模式。
go
语句用法。这将只在其主线程之外执行函数。作为go中的并发使用基本,此模式设计无法通过go
语句从执行函数中获取数据。不能来自main()
线程或任何其他功能。为了与沟通与其需要的任何其他功能/线程channel
。您已经提到了一个模式,其中包含go
个channel
模式。就像我之前提到的那样,第二种模式只是Golang中使用go
语句的channel
个go
模式中的一种。实际上这是一个非常复杂的模式,主要用于从多个频道中选择,并将使用这些频道做更多事情。我将对此模式进行一些细微的解释,如下:
for
循环没有条件语句,类似于while
循环,在任何其他语言(如C或Java)上都有效。这意味着无休止的循环。关于select
和case
声明,如果两个或多个通信案件恰好同时准备好,将随机选择一个
即使你需要在运行的并发/异步函数之间进行通信,我猜你一般不需要它。通常使用通道有更简单的模式来传递线程。
总结回答您的问题:
channel
模式方式。但同样,不仅限于上面提到的第二种模式channel
才能与main()
线程或任何其他线程通信异步任务。它自身的模式实际上取决于您将如何通信(发送/接收)数据/值源(数据库,切片变量等)以及更多其他方面。我建议您详细了解channel
的用法,有很多模式可以解决这个问题。我建议先检查https://gobyexample.com/goroutines。从那里开始,你会在页面底部看到“下一个例子”,它将更深入地了解并发事物。 另外:
go
语句很简单,复杂的事情与channel
的用法有关。为了更好地理解并发通信,我在这里列出了你最好学习的内容。
希望这可以帮助你或者一些人开始使用goroutine和channel来在Golang中使用并发。如果有人喜欢纠正我的答案或要求进一步解释,请随意。谢谢。