TODO
</p>
+<h3 id="net"><a href="/pkg/net/">net</a></h3>
+
+<p><!-- CL -->
+ The case of I/O on a closed network connection, or I/O on a network
+ connection that is closed before any of the I/O completes, can now
+ be detected using the new <a href="/pkg/net/#ErrClosed">ErrClosed</a> error.
+ A typical use would be <code>errors.Is(err, net.ErrClosed)</code>.
+ In earlier releases the only way to reliably detect this case was to
+ match the string returned by the <code>Error</code> method
+ with <code>"use of closed network connection"</code>.
+</p>
+
<h3 id="unicode"><a href="/pkg/unicode/">unicode</a></h3>
<p><!-- CL 248765 -->
import (
"context"
+ "errors"
"fmt"
"internal/poll"
"io"
goto third
}
switch nestedErr {
- case errCanceled, poll.ErrNetClosing, errMissingAddress, errNoSuitableAddress,
+ case errCanceled, ErrClosed, errMissingAddress, errNoSuitableAddress,
context.DeadlineExceeded, context.Canceled:
return nil
}
goto third
}
switch nestedErr {
- case poll.ErrNetClosing, errTimeout, poll.ErrNotPollable, os.ErrDeadlineExceeded:
+ case ErrClosed, errTimeout, poll.ErrNotPollable, os.ErrDeadlineExceeded:
return nil
}
return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
goto third
}
switch nestedErr {
- case errCanceled, poll.ErrNetClosing, errMissingAddress, errTimeout, os.ErrDeadlineExceeded, ErrWriteToConnected, io.ErrUnexpectedEOF:
+ case errCanceled, ErrClosed, errMissingAddress, errTimeout, os.ErrDeadlineExceeded, ErrWriteToConnected, io.ErrUnexpectedEOF:
return nil
}
return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
return fmt.Errorf("error string %q does not contain expected string %q", nestedErr, want)
}
+ if !isShutdown && !errors.Is(nestedErr, ErrClosed) {
+ return fmt.Errorf("errors.Is(%v, errClosed) returns false, want true", nestedErr)
+ }
+
switch err := nestedErr.(type) {
case *OpError:
if err := err.isValid(); err != nil {
goto third
}
switch nestedErr {
- case poll.ErrNetClosing:
+ case ErrClosed:
return nil
}
return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
goto third
}
switch nestedErr {
- case poll.ErrNetClosing, errTimeout, poll.ErrNotPollable, os.ErrDeadlineExceeded:
+ case ErrClosed, errTimeout, poll.ErrNotPollable, os.ErrDeadlineExceeded:
return nil
}
return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
goto third
}
switch nestedErr {
- case poll.ErrNetClosing:
+ case ErrClosed:
return nil
}
return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
import (
"context"
"errors"
+ "internal/poll"
"io"
"os"
"sync"
// error and return a DNSError for which Temporary returns false.
func (e *DNSError) Temporary() bool { return e.IsTimeout || e.IsTemporary }
+// errClosed exists just so that the docs for ErrClosed don't mention
+// the internal package poll.
+var errClosed = poll.ErrNetClosing
+
+// ErrClosed is the error returned by an I/O call on a network
+// connection that has already been closed, or that is closed by
+// another goroutine before the I/O is completed. This may be wrapped
+// in another error, and should normally be tested using
+// errors.Is(err, net.ErrClosed).
+var ErrClosed = errClosed
+
type writerOnly struct {
io.Writer
}