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

cc *_*ung 38 go blocking node.js

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

在Go中,使用通道可以轻松实现非阻塞.

如果有人在go中编写node.js类型的服务器,是否有意义使其无阻塞?例如,让数据库connect()函数返回一个通道,而不是在等待连接发生时阻塞.

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

但......

Jes*_*sta 65

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

在Go中,当goroutine在I/O上阻塞时,会换掉另一个goroutine.Go运行时使用非阻塞I/O系统调用来避免操作系统阻塞线程,因此当第一个等待它的I/O时,可以在其上运行不同的goroutine.

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

  • 是的,最好让你的所有功能阻止goroutine.这使它们更容易使用和思考.呼叫者总是可以轻松地使他们自己无阻塞. (10认同)
  • @chmike切换goroutine的成本很小,类似于在事件循环中切换事件的成本. (4认同)

Eva*_*haw 25

写阻塞功能.该语言允许您轻松地将同步调用转换为异步调用.

如果要异步调用函数,请使用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
Run Code Online (Sandbox Code Playgroud)

  • 我之所以这样说是因为你总能绕过阻塞,你应该总是编写阻塞函数. (6认同)
  • 谢谢你的例子,但是我的问题不是_how_绕过阻止,但是_Way_在golang中编写非阻塞本身是一个有价值的目标.对不起,如果我没说清楚;) (2认同)

tyl*_*erl 18

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

回调(因为你习惯于在js中使用)允许基本上相同的底层机制,但可以说程序员需要更多的心理体操.

在Go中,在函数调用之后立即指定要在函数调用之后运行的代码,而不是将其定义为回调.您希望与执行路径并行运行的代码应该包含在goroutine中,并通过通道进行通信.


Nat*_*ead 10

对于典型的Web服务器类型的应用程序,我建议不要使所有内容都异步.有几个原因.

  • 串行阻塞代码比异步代码更容易推理(更容易看到错误)

  • golang错误处理基于defer(),panic()和recover(),这可能无法为您提供100%异步代码所需的内容

  • 如果你不小心的话,Goroutines会泄漏[一次讨论].您拥有的异步行为越多,追踪这些类型的问题就越难以显示出来.

一种策略是将异步性集中在一个高水平,并让其他一切阻塞.因此,您可能有一个"数据库处理程序"blob,它在逻辑上与"请求处理程序"blob不同.它们都在不同的goroutine中运行并使用通道进行通信.但是在"数据库处理程序"中,建立数据库连接和执行每个查询的调用都是阻塞的.

您不必选择100%异步或0%异步.

  • @cc_young connect() 和 query() 将在我的示例中阻塞并由数据库处理程序调用。数据库处理程序将有一个通道接口,其中包含诸如“更新用户昵称”、“获取好友列表”之类的操作。要获取好友列表,您可以在“好友列表请求”频道上将用户名和响应频道作为请求发送。数据库处理程序获取请求,首先检查本地缓存,如果缓存立即返回。否则它会在数据库(块)上执行查询。一旦结果可用,将它们发送到响应通道。 (2认同)
  • 假设golang错误处理基于defer(),panic()和recover()不是正确的语句.defer()有很多用途.panic()很少使用,应尽可能避免.recover()是语言的补充.在Golang中,错误处理基于函数内部的仔细错误管理,以及错误变量的惯用返回,让调用者决定做什么(忽略它,修复它或将其报告给它自己的调用者). (2认同)

uri*_*iel 6

阻塞接口总是比非阻塞接口更简单,更好.Go的优点在于它允许您以简单,易于推理的方式编写并发(和并行)代码,阻塞样式.

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