How to check a net.Conn is closed?

Viewed 6130

Or how to check it is available for Read or Write in loop? If the conn is closed or not available, we should stop the loop.

For example:

package main

import "net"

func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:1111")
    defer conn.Close()
    for {
        buf := make([]byte, 1, 1)
        n, err := conn.Read(buf)
        if err != nil {
            // currently we can only stop the loop
            // when occur any errors
            log.Fatal(err)
        }
    }
}
2 Answers

If you are using Go 1.16 or newer and only working with the standard libraries (not some arbitrary networking stack), you can use a function like this to check the closed errors and handle them differently than other errors:

func isNetConnClosedErr(err error) bool {
    switch {
    case
        errors.Is(err, net.ErrClosed),
        errors.Is(err, io.EOF),
        errors.Is(err, syscall.EPIPE):
        return true
    default:
        return false
    }
}

Note that there is an os.ErrClosed error (alias for fs.ErrClosed) that you could add if you were dealing with files, but you don't need it when only using the net package. While your code only shows a client, there is probably a server side doing listener.Accept() that gets closed by a different go process and you don't want to log nasty errors when that happens, so you want to have net.ErrClosed in the list above. As for syscall.EPIPE, this comes in handy when writing to a remote end that already closed the connection. Remember that with networking connections, you may not get the EPIPE on the 1st write, as the OS may need to send some data to discover that the remote end was closed.

Related