IO对goroutine的回调

IO对goroutine的回调,go,Go,我是戈朗的初学者。看看所有的golang教程,看起来您应该为所有内容创建Goroutine。源于C中的libuv,您可以在单个线程上为套接字读/写定义回调,在golang中为任何需要的IO任务创建嵌套goroutine是实现这一点的正确方法吗 例如,以nginx为例,其中一个线程将处理多个连接。要在golang中实现类似的功能,我们需要为每个连接提供goroutine?Go在编写网络服务的工具领域特别突出,因为它将I/O感知集成到运行时调度器中,为任何运行中的Go程序提供动力 基本思想大致是这样

我是戈朗的初学者。看看所有的golang教程,看起来您应该为所有内容创建Goroutine。源于C中的libuv,您可以在单个线程上为套接字读/写定义回调,在golang中为任何需要的IO任务创建嵌套goroutine是实现这一点的正确方法吗


例如,以nginx为例,其中一个线程将处理多个连接。要在golang中实现类似的功能,我们需要为每个连接提供goroutine?

Go在编写网络服务的工具领域特别突出,因为它将I/O感知集成到运行时调度器中,为任何运行中的Go程序提供动力

基本思想大致是这样的:goroutine在套接字上执行正常的、顺序的、无回调的操作,即普通读取和普通写入操作,一旦下一个I/O操作阻塞(是的,类Unix内核上的相关系统调用返回
ewoodblock
),goroutine就会挂起,它的套接字被分发到名为“netpoller”的运行时组件中,该组件是使用平台本机套接字I/O多路复用器(如
epoll
kqueue
或IOCP)实现的,goroutine运行的OS线程被分发给另一个要运行的goroutine。一旦netpoller发出套接字上的I/O信号导致goroutine挂起,就可以继续进行,调度程序将goroutine排队等待执行,然后它继续精确地运行在停止的位置

因此,在Go中编写网络服务时采用的通常模型是每个套接字有一个goroutine。在编写普通TCP服务器时,您应该自己创建一个goroutine(并在侦听器接受客户端连接后将其返回的套接字交给它)。
net/http.Server
内置了这种行为,因为它创建一个goroutine来为每个传入的客户端请求提供服务(实际上,对于http/1.x,每个连接创建两个甚至三个goroutine,但对http请求处理程序来说是不可见的)

现在,我们刚刚介绍了基本知识。当然,可能有正当的理由让额外的goroutine来处理完成请求所需执行的任务,这就是@Volker所指的

更多信息:

  • -一篇关于I/O多路复用作为库实现与在核心中实现的经典文章
  • );另请参见和
  • 它实现了与Go非常相似的方法,只是在低得多的级别上。它的文档对在Go中实现的方法很有见解。
    这是最近的一次尝试 同样的问题,由Go的一个创造者提出

“在golang中为任何需要的IO任务创建嵌套Goroutine是实现这一目标的正确方法吗?”不,当然不是。请注意,“any”即使不是解决单个问题的正确方法,也没有空间回答“yes”。你的实际问题是什么?nginx的例子是错误的:来自net/http的内置Web服务器已经为您完成了所有这些,因此您不需要“每个连接都需要goroutine”,您已经为每个请求提供了goroutine。我只是想了解golang的设计理念。假设我从头开始构建代理服务器,不使用net/http,只使用net.Listen()。在nginx中,一个线程将通过多个连接进行多路复用,这在golang中是可能的/推荐的。所以我的问题是,为每个连接创建一个新的goroutine,并在其中为任何需要的IO创建嵌套的goroutine,或者在go中是否有不同的方法?创建goroutine。请注意,goroutine和线程是不同的东西。当然,您可以重新实现nginx在Go中的功能,但您为什么要这样做呢?我怀疑研究这个特定的问题并将其与一个不同的解决方案进行比较不会对Go中的并发性产生太多的影响。谢谢,这非常有帮助!