猿问

在Go中侦听事件的惯用方法是什么?

几个月前,我在考虑如何在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秒。有没有更惯用的方法来创建事件循环?


慕工程0101907
浏览 223回答 1
1回答

波斯汪

我认为Go中的事件循环不必是循环。在单独的goroutine中处理关闭和连接似乎更简单:go func() {&nbsp; &nbsp; <-s.closeChan&nbsp; &nbsp; // close server, release resources, etc.&nbsp; &nbsp; s.listener.Close()}()for {&nbsp; &nbsp; conn, err := s.listener.Accept()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// log, return&nbsp; &nbsp; }&nbsp; &nbsp; // handle conn routine}请注意,您也可以在不使用通道的情况下直接在“关闭”函数中关闭侦听器。我在这里所做的是使用Listener.Accept的错误返回值来促进例程间的通信。如果在关闭和连接处理实现的某个时候需要保护要在回答时关闭的某些资源,则可以使用Mutex。但是通常可以避免这种情况。
随时随地看视频慕课网APP

相关分类

Go
我要回答