Go有回调概念吗?

A-l*_*bby 22 go node.js

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

我觉得Go也可以像Node.js一样回调,但是以同步的方式.因为我们可以传递匿名函数并做关闭事情

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

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

tux*_*21b 43

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

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

doSomething1(arg1, arg2, function() {
  doSomething2(arg1, arg2, function() {
    doSomething3(function() {
      // done
    });
  });
});
somethingElse();
Run Code Online (Sandbox Code Playgroud)

doSomething1可能需要很长时间才能执行(因为它需要从网络中读取),但您的程序仍然可以在同一时间执行somethingElse.之后doSomething1被执行,你要调用doSomething2doSomething3.

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

go func() {
  doSomething1(arg1, arg2)
  doSomething2(arg1, arg2)
  doSomething3()
  // done
}()
somethingElse()
Run Code Online (Sandbox Code Playgroud)

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

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


nem*_*emo 10

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

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

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

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