Getting rid of goto without duplication in Go Consider the following function:

func Listen(username string) (net.Listener, error) {
    path := filepath.Join(socketsDir, username)

    oldUmask := syscall.Umask(^0600)
    defer syscall.Umask(oldUmask)

    listener, err := net.Listen("unixpacket", path)
    if err != nil {
        return nil, err
    }

    passwd, err := passwd.Getpwnam(username)
    if err != nil {
        goto chownFailed
    }

    err = os.Chown(path, int(passwd.Uid), os.Getgid())
    if err != nil {
        goto chownFailed
    }

    return listener, err

chownFailed:
    listener.Close()
    return nil, err
}


I think this way of error handling is ugly. Is there a way to get rid of the goto without duplicating the call to listener.Close?
You could use defer along with named return values.

E.g.:

listener, err := net.Listen("unixpacket", path)
if err != nil {
    return nil, err
}
defer func() {
    if err != nil {
        listener.Close()
    }
}()

// rest of function that just does "return nil, err" as needed


A runnable playground version of this:
https://play.golang.org/p/lKnGyzbp_3

Note, normally you'll see things like this in Go:

f, err := os.Open("somefile")
if err != nil {
    return err
}
defer f.Close()


That is easier and works for the common case where the thing (a file here) is being used just inside the function itself and needs to always be closed before returning to the caller. In the question however, the listening socket needs to be closed only if there is a error after it was opened. If there is no error it needs to be left open and returned to the caller. That's why the defer'ed function checks err (which it can do as long as it's a named returned value; you can even change named return values in a defer'ed function).