Go有回调概念吗?

时间:2014-05-17 08:15:25

标签: node.js go

我发现很多会谈说Node.js因为回调地狱而糟糕,Go因为它的同步模型而很好。

我觉得Go也可以像Node.js一样回调,但是以同步的方式。我们可以pass anonymous function and do closure things

那么,他们为什么要在回调视角中比较Go和Node.js,好像Go不能成为回调地狱。

或者我误解了Go中回调和匿名函数的含义?

2 个答案:

答案 0 :(得分:42)

很多事情需要时间,例如等待网络套接字,文件系统读取,系统调用等。因此,许多语言,或者更确切地说是他们的标准库,包括其功能的异步版本(通常除了同步版本),以便您的程序能够在平均时间内做其他事情。

在node.js中,事情更加极端。它们使用单​​线程事件循环,因此需要确保您的程序永远不会阻塞。它们有一个非常好的标准库,它是围绕异步的概念构建的,它们使用回调来在事情准备就绪时通知你。代码基本上如下所示:

doSomething1(arg1, arg2, function() {
  doSomething2(arg1, arg2, function() {
    doSomething3(function() {
      // done
    });
  });
});
somethingElse();

doSomething1可能需要很长时间才能执行(例如,因为它需要从网络中读取),但您的程序仍然可以同时执行somethingElse。执行doSomething1后,您需要致电doSomething2doSomething3

Go on另一方面基于goroutines和渠道的概念(google for" Communicating Sequential Processes",如果你想了解更多关于抽象概念的话)。 Goroutines非常便宜(你可以同时运行几千个),因此你可以在任何地方使用它们。 Go中的相同代码可能如下所示:

go func() {
  doSomething1(arg1, arg2)
  doSomething2(arg1, arg2)
  doSomething3()
  // done
}()
somethingElse()

尽管node.js专注于仅提供异步API,但Go通常鼓励您只编写同步API(没有回调或通道)。对doSomething1的调用将阻止当前goroutine,doSomething2将仅在doSomething1完成后执行。但这在Go中不是问题,因为通常有其他可用的goroutine可以安排在系统线程上运行。在这种情况下,somethingElse是另一个goroutine的一部分,可以在此期间执行,就像在node.js示例中一样。

我个人更喜欢Go代码,因为它更容易阅读和推理。 Go的另一个优点是它也适用于计算繁重的任务。如果你在node.js中开始一个不需要等待文件系统调用网络的大量计算,这个计算基本上会阻塞你的事件循环。另一方面,Go的调度程序将尽力在几个系统线程上调度goroutine,如果你的CPU支持,操作系统可以并行运行这些线程。

答案 1 :(得分:10)

  

我觉得Golang也可以像Node.js那样以同步的方式进行回调。因为我们可以传递匿名函数并做关闭事情

     

那么,为什么他们在回调视角比较Golang和Node.js,好像Golang不能成为回调地狱。

是的,当然也有可能在Go中搞砸了。您没有看到与node.js一样多的回调的原因是Go有通信渠道,这允许在不使用回调的情况下构建代码的方法。

因此,由于存在通道,因此不经常使用回调,因此不太可能在回调受感染的代码上发现错误。当然,这并不意味着你也不能用频道编写可怕的代码......