node.js 在 Go 中,编写非阻塞代码有意义吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6328679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Go, does it make sense to write non-blocking code?
提问by cc young
coming from node.js point of view, where all code is non-blocking.
从 node.js 的角度来看,所有代码都是非阻塞的。
In Go, non-blocking is easily achieved using channels.
在 Go 中,使用通道很容易实现非阻塞。
if one were writing a node.js type server in go, does it make sense to make it non-blocking? for example, having a database connect() function return a channel, as versus blocking while waiting for the connection to occur.
如果有人在 go 中编写 node.js 类型的服务器,让它非阻塞有意义吗?例如,让数据库 connect() 函数返回一个通道,而不是在等待连接发生时阻塞。
to me, this seems the correct approach
对我来说,这似乎是正确的方法
but ...
但 ...
回答by Jessta
Blocking and non-blocking aren't really about performance, they are about an interface. If you have a single thread of execution then a blocking call prevents your program from doing any useful work while it's waiting. But if you have multiple threads of execution a blocking call doesn't really matter because you can just leave that thread blocked and do useful work in another.
阻塞和非阻塞实际上与性能无关,它们与接口有关。如果你只有一个执行线程,那么阻塞调用会阻止你的程序在等待时做任何有用的工作。但是如果你有多个执行线程,阻塞调用并不重要,因为你可以让那个线程被阻塞并在另一个线程中做有用的工作。
In Go, a goroutine is swapped out for another one when it blocks on I/O. The Go runtime uses non-blocking I/O syscalls to avoid the operating system blocking the thread so a different goroutine can be run on it while the first is waiting for it's I/O.
在 Go 中,当一个 goroutine 阻塞 I/O 时,它会被替换为另一个 goroutine。Go 运行时使用非阻塞 I/O 系统调用来避免操作系统阻塞线程,以便在第一个等待它的 I/O 时可以在它上面运行不同的 goroutine。
Goroutines are really cheap so writing non-blocking style code is not needed.
Goroutines 真的很便宜,所以不需要编写非阻塞风格的代码。
回答by Evan Shaw
Write blocking functions. The language allows you to easily turn a synchronous call into an asynchronous one.
编写阻塞函数。该语言允许您轻松地将同步调用转换为异步调用。
If you want to call a function asynchronously, use a go statement. Something like this:
如果要异步调用函数,请使用 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
回答by tylerl
In Go, system calls are implemented in a non-blocking way using the most efficient underlying mechanism that the OS supports (e.g. epoll). If you have no other code to run while you wait for the result of a call, then it blocks the thread (for lack of a better thing to do), but if you have alternate goroutines active, then they will run instead.
在 Go 中,系统调用是使用操作系统支持的最有效的底层机制(例如epoll)以非阻塞方式实现的。如果您在等待调用结果时没有其他代码可以运行,那么它会阻塞线程(因为没有更好的事情要做),但是如果您有备用 goroutine 处于活动状态,那么它们将改为运行。
Callbacks (as you're used to using in js) allow for essentially the same underlying mechanics, but with arguably more mental gymnastics necessary for the programmer.
回调(正如您习惯在 js 中使用的那样)允许基本相同的底层机制,但可以说程序员需要更多的心理体操。
In Go, your code to run after a function call is specified immediately following the function call rather than defined as a callback. Code that you want to run parallel to an execution path should be wrapped in a goroutine, with communication through channels.
在 Go 中,在函数调用之后运行的代码是在函数调用之后立即指定的,而不是定义为回调。您希望与执行路径并行运行的代码应封装在 goroutine 中,并通过通道进行通信。
回答by Nathan Whitehead
For typical web-server type applications, I would recommend notmaking everything asynchronous. There are a few reasons.
对于典型的 Web 服务器类型的应用程序,我建议不要将所有内容都设为异步。有几个原因。
It's easier to reason about serial blocking code than async code (easier to see bugs)
golang error handling is based on defer(), panic(), and recover(), which probably won't give you what you want with 100% asynchronous code
Goroutines can leak if you're not careful [one discussion]. The more async behavior you have, the harder it becomes to track down these types of problems and the more likely they are to show up.
串行阻塞代码比异步代码更容易推理(更容易看到错误)
golang 错误处理基于 defer()、panic() 和 recover(),这可能不会为您提供 100% 异步代码所需的内容
如果你不小心,Goroutines 可能会泄漏[一个讨论]。您的异步行为越多,就越难追踪这些类型的问题,而且它们出现的可能性也越大。
One strategy is to focus the asynchonicity at a high level and leave everything else blocking. So you might have a "database handler" blob that is logically distinct from the "request handler" blob. They both run in separate goroutines and communicate using channels. But within the "database handler", the calls to establish a database connection and execute each query are blocking.
一种策略是将异步性集中在高层次上,而让其他一切都阻塞。因此,您可能有一个“数据库处理程序”blob,它在逻辑上与“请求处理程序”blob 不同。它们都在单独的 goroutine 中运行并使用通道进行通信。但是在“数据库处理程序”中,建立数据库连接和执行每个查询的调用是阻塞的。
You don't have to choose 100% asynchronous or 0% asynchronous.
您不必选择 100% 异步或 0% 异步。
回答by uriel
Blocking interfaces are always simpler and better than non-blocking ones. The beauty of Go is that it allows you to write concurrent (and parallel) code in a simple, and easy to reason about, blocking style.
阻塞接口总是比非阻塞接口更简单、更好。Go 的美妙之处在于它允许您以简单且易于推理的阻塞风格编写并发(和并行)代码。
The fashion for non-blocking programming is all due to deficiencies in the languages people are using (specially JavaScript), not because non-blocking programming is intrinsically better.
非阻塞编程的流行完全是由于人们使用的语言(特别是 JavaScript)的缺陷,而不是因为非阻塞编程本质上更好。

