Go's net package provides the ability to create listening servers. However, gracefully stopping these servers can be challenging due to the blocking nature of the listen.Accept method.
One common approach to stopping a server is to close the listening socket. However, this can result in errors that cannot be distinguished from genuine errors during connection acceptance. As a result, the following code snippet exhibits this issue:
// ... // Listen for incoming connections func (es *EchoServer) serve() { for { conn, err := es.listen.Accept() // FIXME: I'd like to detect "use of closed network connection" here // FIXME: but it isn't exported from net if err != nil { log.Printf("Accept failed: %v", err) break } // ... } // ... }
To address this limitation, we can utilize the es.done channel to send a signal before the server is stopped. Here's how the code can be improved:
// ... // Listen for incoming connections func (es *EchoServer) serve() { for { conn, err := es.listen.Accept() if err != nil { select { case <-es.done: // Server is being stopped, so we can exit without logging the error. default: log.Printf("Accept failed: %v", err) } return } // ... } } // Stop the server by closing the listening socket func (es *EchoServer) stop() { es.done <- true es.listen.Close() }
By sending a value to the es.done channel before closing the listening socket, the serve function can determine when the server is being stopped and gracefully exit without logging spurious errors.
The above is the detailed content of How Can I Gracefully Stop a Go Listening Server Without Spurious Errors?. For more information, please follow other related articles on the PHP Chinese website!