在Go中,写非阻塞代码是否有意义?

来自node.js的观点,所有的代码都是非阻塞的。

在Go中,使用频道很容易实现非阻塞。

如果有人正在写一个node.jstypes的服务器,是否有意义,使其非阻塞? 例如,有一个数据库连接()函数返回一个通道,而不是等待连接发生阻塞。

对我来说,这似乎是正确的做法

但是…

阻塞和非阻塞不是关于性能,而是关于接口。 如果你有一个单线程的执行,那么阻塞调用将阻止你的程序在等待的时候做任何有用的工作。 但是如果你有多个执行线程,阻塞调用并不重要,因为你可以把这个线程阻塞,并在另一个线程中做有用的工作。

在Go中,当它阻塞I / O时,一个goroutine被换出另一个。 Go运行时使用非阻塞的I / O系统调用来避免操作系统阻塞线程,所以当第一个等待它的I / O时,可以运行不同的configuration程序。

Goroutines非常便宜,因此不需要编写非阻塞式的代码。

编写阻塞函数。 该语言允许您轻松地将同步呼叫转换为asynchronous呼叫。

如果你想asynchronous调用一个函数,使用go语句。 像这样的东西:

c := make(chan bool) go func() { blockingFunction() c <- true }() // do some other stuff here while the blocking function runs // wait for the blocking function to finish if it hasn't already <-c 

在Go中,系统调用是使用OS支持的最有效的底层机制(如epoll )以非阻塞的方式实现的。 如果在等待调用的结果时没有其他代码运行,那么它会阻塞该线程(因为没有更好的办法),但是如果有其他的goroutine处于活动状态,那么它们将运行。

callback(正如你在js中使用的那样)允许基本上相同的基本机制,但是可以说程序员需要更多的心理体操。

在Go中,函数调用后运行的代码在函数调用后立即指定,而不是定义为callback。 你想和一个执行path并行运行的代码应该封装在一个goroutine中,通过通道进行通信。

对于典型的Web服务器types的应用程序,我build议不要使所有的事情都是asynchronous的 有几个原因。

  • 关于串行阻止代码比asynchronous代码更容易理解(更容易发现错误)

  • golangerror handling是基于defer(),panic()和recover(),这可能不会给你你想要的100%asynchronous代码

  • 如果你不小心的话,Goroutine可能会泄漏[一个讨论] 。 你有更多的asynchronous行为,追踪这些types的问题变得越困难,他们越有可能出现。

其中一个策略就是把异化性集中在一个高层次上,而把所有的东西都封锁起来。 所以你可能有一个“数据库处理程序”blob逻辑上不同于“请求处理程序”blob。 他们都在不同的办公室运行,并使用渠道进行沟通。 但是在“数据库处理程序”中,build立数据库连接和执行每个查询的调用都是阻塞的。

您不必select100%asynchronous或0%asynchronous。

阻塞接口总是比非阻塞接口更简单和更好。 Go的优点在于,它允许您通过简单易懂的原因编写并发(并行)代码,阻止风格。

非阻塞编程的时尚都是由于人们使用的语言(特别是JavaScript)的缺陷,而不是因为非阻塞编程在本质上更好。