Reader/Writer/Close
郭學聰 Hsueh-Tsung KuoThu, 27 Dec 2018
type Reader interface { Read(p []byte) (n int, err error) }
Key point:
n > 0
bytes returned before considering the error err.func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) { if len(buf) < min { return 0, ErrShortBuffer } for n < min && err == nil { var nn int nn, err = r.Read(buf[n:]) n += nn } if n >= min { err = nil } else if n > 0 && err == EOF { err = ErrUnexpectedEOF } return }
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) { b.lastRead = opInvalid for { i := b.grow(MinRead) b.buf = b.buf[:i] m, e := r.Read(b.buf[i:cap(b.buf)]) if m < 0 { panic(errNegativeRead) } b.buf = b.buf[:i+m] n += int64(m) if e == io.EOF { return n, nil // e is EOF, so return nil explicitly } if e != nil { return n, e } } }
type Writer interface { Write(p []byte) (n int, err error) }
Key point:
n < len(p)
.type Closer interface { Close() error }
Key point:
type ReaderAt interface { ReadAt(p []byte, off int64) (n int, err error) }
Key point:
n < len(p)
, it returns a non-nil error explaining why more bytes were not returned.to ensure Read() fill buf
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) func ReadFull(r Reader, buf []byte) (n int, err error)
https://golang.org/pkg/io/#ReadAtLeast
https://golang.org/pkg/io/#ReadFull
or use utility function to read/write all
var Discard io.Writer = devNull(0) func NopCloser(r io.Reader) io.ReadCloser func ReadAll(r io.Reader) ([]byte, error) func ReadDir(dirname string) ([]os.FileInfo, error) func ReadFile(filename string) ([]byte, error) func TempDir(dir, prefix string) (name string, err error) func TempFile(dir, pattern string) (f *os.File, err error) func WriteFile(filename string, data []byte, perm os.FileMode) error
func RWBY() (err error) { defer f.Close() }
func RWBY() (err error) { defer func() { cerr := f.Close() if err == nil { err = cerr } }() }
func safeClose(c io.Closer, err *error) { cerr := c.Close() if *err == nil { *err = cerr } } func RWBY() (err error) { defer safeClose(f, &err) }
type WriterCounter struct { writer io.Writer count int64 } func (wc *WriterCounter) Write(p []byte) (n int, err error) { n, err = wc.writer.Write(p) atomic.AddInt64(&wc.count, int64(n)) return } func (wc *WriterCounter) Count() int64 { return atomic.LoadInt64(&wc.count) } func NewWriterCounter(w io.Writer) *WriterCounter { return &WriterCounter{writer: w} }
type writeNopCloser struct { io.Writer } func (_ writeNopCloser) Close() error { return nil } func WriteNopCloser(w io.Writer) io.WriteCloser { return writeNopCloser{Writer: w} }
type ChainCloseReadCloser struct { io.ReadCloser underlyingReadClosers []io.ReadCloser } func (chainCloseReadCloser *ChainCloseReadCloser) Close() error { err := chainCloseReadCloser.ReadCloser.Close() for _, underlyingReadCloser := range chainCloseReadCloser.underlyingReadClosers { cerr := underlyingReadCloser.Close() // always return first close error if err == nil { err = cerr } } return err } func NewChainCloseReadCloser(readCloser io.ReadCloser, underlyingReadClosers ...io.ReadCloser) io.ReadCloser { return &ChainCloseReadCloser{ReadCloser: readCloser, underlyingReadClosers: underlyingReadClosers} }
Reader/Writer/Closer 博大精深
Hsueh-Tsung KuoThu, 26 Apr 2018