如何知道net.Listener何时正确关闭?

I have the following code:

server := &http.Server{Addr: addr, Handler: r}

l, err := net.Listen("tcp", addr)
if err != nil {
    logging.Error("Failed opening socket: %s", err)
}

if err := server.Serve(l); err != nil {
    // error handling
}

When l.Close() is called, server.Serve(l) will exit with an error. I would like to know whether this is truly an error or just the result of someone calling l.Close() (which is non error for me).

Is there a proper way to do this?

Some hack-ish way about TCP socket:

read_len, err := conn.Read(request)

if err != nil {

  if err.Error() == "use of closed network connection" { 
    // Do something when socket closed
    break
  }

Try if err.Error() == "use of closed network connection" under if err := server.Serve(l); err != nil {, or in your TCP handler function.

With interfaces that implement io.ReadWriteCloser you typically get back an io.EOF and io.ErrUnexpectedEOF error. net.Listener implements io.Closer, so I would expect it to also return this error, but it unfortunately does not follow this convention. Instead, it returns a privately declared errClosing in net.go.

Errors returned by net.Listener are wrapped in net.OpError. This struct has some additional information that may be helpful - specifically "Op" and "Err". "Op" tells you where the error occurred. When you execute Close() error you get "accept" back. The documentation says you can also get "read" and "write" back.

To get net.OpError, you can do this:

err := server.Serve(l)
if opErr, ok := err.(*net.OpError); ok {
    // opErr.Op, opErr.Err, ...
}

Or like this (assuming that net.Listener always returns a net.OpError):

err := server.Serve(l).(*net.OpError)

net.OptError.Err returns the original error, which would be helpful if the error was exported. Either way I don't recommend checking the string as that could break in future versions. It's better to compare the error directly to the exported error, which you don't have.

net.OptError also has a Temporary() bool function declared. The net/http package uses this to re-establish the connection on a increasing interval. So in the case of net/http I would assume that any error that returns would be a result of calling Close() error. Otherwise Temporary() bool would return true, which net/http catches for you.