# src.lwithers.me.uk/go/byteio [![GoDoc](https://godoc.org/src.lwithers.me.uk/go/byteio?status.svg)](https://godoc.org/src.lwithers.me.uk/go/byteio) This package provides two interfaces, `Reader` and `Writer`, which capture the most common byte-oriented methods for I/O, namely `Read([]byte)`, `ReadByte()` and `ReadRune()` (plus the equivalent writing methods). This is useful because sometimes you simply want to perform byte-oriented I/O without knowing whether you have an underlying `bytes.Buffer` or `bufio.Reader` etc. Furthermore, as a convenience, there are functions which automatically wrap any `io.Reader` or `io.Writer` with a bufio equivalent if necessary. These allow for simple byte-oriented I/O operations on arbitrary reader / writer interfaces with minimal boilerplate. Example of a method using the `byteio.Reader` interface: ``` func ReadUint16LE(r byteio.Reader) (uint16, error) { var n uint16 if x, err := r.ReadByte(); err != nil { return 0, err } else { n = uint16(x) } if x, err := r.ReadByte(); err != nil { return 0, err } else { n |= uint16(x) << 8 } return n, nil } ``` Example of something calling this function: ``` var r io.Reader // … br := byteio.NewReader(r) n, err := ReadUint16LE(br) ``` Example of using the writer interface: ``` var w io.Writer // … bw := byteio.NewWriter(w) defer byteio.FlushIfNecessary(bw) err := WriteUint16LE(bw, 0x5432) ``` The `byteio.FlushIfNecessary` method determines whether its argument has a `Flush()` method or not, and if it does, calls it. This allows the caller to write non-conditional code, not having to check whether `bw` is a `bufio.Writer` (which needs a flush) or a `bytes.Buffer` (which does not), etc.