-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Description
There are many APIs in Go that append to a []byte and return a []byte.
Unfortunately, these APIs operate poorly with bufio.Writer since that type only accepts []byte as an input (via the Write method) and never provides a []byte. This requires logic trying to combine append-like functionality with bufio.Writer to be responsible for allocating a buffer, when bufio.Writer already has a buffer.
I propose the addition of a new method that provides access to the underlying []byte:
// AvailableBuffer returns an empty buffer with b.Available capacity.
// This buffer is intended to be appended to and
// passed to an immediately succeeding Write call.
func (b *Writer) AvailableBuffer() []byte {
return b.buf[b.n:][:0]
}Example usage:
var bw *bufio.Writer = ...
b := bw.AvailableBuffer()
b = strconv.AppendUint(b, ...)
bw.Write(b)In the common cases where bw.Available() is large enough, strconv.AppendUint appends to the buffer without allocating. When the buffer is passed to Write, the underlying call to copy returns immediately without actually copying since the source and destination are identical. This saves us both an allocation and a copy.
In the rare case where it allocates, the subsequent Write call still works as expected, but needs to copy.
The detriment of this API is that it exposes the internal buffer of bufio.Writer when it was previously impossible to access it. However, the other types in the package (i.e., Reader and Scanner) already provide unsafe access to the underlying buffer via the Reader.Peek, Reader.ReadSlice, and Scanner.Bytes methods.