go func中plain go func和for循环之间的区别

时间:2018-01-22 03:05:20

标签: go channel goroutine

我对go func中的plain go func和for循环之间的区别有一些疑问:

  1. Plain go Func:

    func asyncTask(){
        //...something
    }
    

    为了触发asyncTask,我们可以简单地说:

    func main(){
        go asyncTask()
    }
    
  2. 制作一个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
    }
    
  3. 我的问题是:

    1. 我理解第二种情况最适合我们希望管理队列中的异步任务的情况。 但是说出经常触发的异步任务(不能阻止)的性能,哪种方法更好?

    2. 在GoLang中处理异步任务是否有一般的最佳做法?

3 个答案:

答案 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循环

不同用途更多。

在回答你的问题之前,我想尝试简单解释你提到的两种模式。

  1. 第一种模式是非常基本的go语句用法。这将只在其主线程之外执行函数。作为go中的并发使用基本,此模式设计无法通过go语句从执行函数中获取数据。不能来自main()线程或任何其他功能。为了沟通与其需要的任何其他功能/线程channel。您已经提到了一个模式,其中包含gochannel模式。
  2. 就像我之前提到的那样,第二种模式只是Golang中使用go语句的channelgo模式中的一种。实际上这是一个非常复杂的模式,主要用于从多个频道中选择,并将使用这些频道做更多事情。我将对此模式进行一些细微的解释,如下:

    • for循环没有条件语句,类似于while循环,在任何其他语言(如C或Java)上都有效。这意味着无休止的循环。
    • 由于它是无限循环,因此需要一个通常从可用通道检查的条件来检查。例如,当某个频道关闭时,它就会结束。
    • 关于selectcase声明,如果两个或多个通信案件恰好同时准备好,将随机选择一个

    • 即使你需要在运行的并发/异步函数之间进行通信,我猜你一般不需要它。通常使用通道有更简单的模式来传递线程。

  3. 总结回答您的问题:

    1. 哪种方法更适合做异步任务实际上取决于你的需要。有几种模式不限于你上面提到的。如果你需要只是异步执行函数,第一个模式就可以了,否则你需要一个channel模式方式。但同样,不仅限于上面提到的第二种模式
    2. 你提到的这两种模式对我来说都是常见的做法。但我想通常我们经常需要至少一个channel才能与main()线程或任何其他线程通信异步任务。它自身的模式实际上取决于您将如何通信(发送/接收)数据/值源(数据库,切片变量等)以及更多其他方面。我建议您详细了解channel的用法,有很多模式可以解决这个问题。我建议先检查https://gobyexample.com/goroutines。从那里开始,你会在页面底部看到“下一个例子”,它将更深入地了解并发事物。
    3. 另外:

      go语句很简单,复杂的事情与channel的用法有关。为了更好地理解并发通信,我在这里列出了你最好学习的内容。

      • 够程
      • 频道方向(发送/接收/单向)
      • 沟通顺序的渠道概念/行为 流程(CSP)。关于发送/接收行为的“阻止”和“继续”行为是某种形式。
      • 缓冲频道
      • 无缓冲频道
      • 关于频道的更多信息:)

      希望这可以帮助你或者一些人开始使用goroutine和channel来在Golang中使用并发。如果有人喜欢纠正我的答案或要求进一步解释,请随意。谢谢。