events - 在 Go 中监听事件的惯用方法是什么?

标签 events concurrency go idioms event-loop

几个月前,我在考虑如何在 Go 中为 RPC 库实现一个可关闭事件循环。我设法像这样关闭服务器:

type Server struct {
    listener net.Listener
    closeChan chan bool
    routines sync.WaitGroup
}

func (s *Server) Serve() {
    s.routines.Add(1)
    defer s.routines.Done()
    defer s.listener.Close()

    for {
        select {
            case <-s.closeChan:
                // close server etc.
            default:
                s.listener.SetDeadline(time.Now().Add(2 * time.Second))
                conn, _ := s.listener.Accept()
                // handle conn routine
        }
    }
}

func (s *Server) Close() {
    s.closeChan <- true // signal to close serve routine
    s.routines.Wait()
}

我发现此实现的问题是它涉及超时,这意味着最短关闭时间比实际时间多了 2 秒。有没有更惯用的创建事件循环的方法?

最佳答案

我认为 Go 中的事件循环不需要是循环。

在单独的 goroutine 中处理关闭和连接似乎更简单:

go func() {
    <-s.closeChan
    // close server, release resources, etc.
    s.listener.Close()
}()
for {
    conn, err := s.listener.Accept()
    if err != nil {
         // log, return
    }
    // handle conn routine
}

请注意,您也可以直接在 Close 函数中关闭监听器,而不使用 channel 。我这里所做的就是利用Listener.Accept的错误返回值来方便例程间的通信。

如果在关闭和连接处理实现的某个时刻您需要保护在应答时关闭的某些资源,您可以使用 a Mutex 。但通常可以避免这种情况。

关于events - 在 Go 中监听事件的惯用方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13507568/

相关文章:

javascript - 将多个事件绑定(bind)到存储在变量中的元素

javascript - 尝试更改父级的 jQuery 单击处理程序会触发新的单击事件

concurrency - 关于 DMA 和 CPU 并发

c# - 多个并发请求之间的 token 共享 C#

reflection - 如何使用反射在golang中创建具有给定名称(字符串)的数组

for-loop - for 循环中的 goroutines 问题

jquery - 防止click事件影响父jquery

.net - .net 事件的性能影响

java - 在 Java 中为线程添加额外的方法?

http - 如何在http get请求中设置 header ?