Description
Currently, io.CopyBuffer uses WriteTo if the src supports it and ReadFrom if the dst supports it, presumably to avoid an allocation.
The problem is that there exist certain io.ReaderFrom that are not efficient 100% of the time. For example, consider the following implementation of ReadFrom:
type myWriter struct {
w io.Writer
}
func (mw *myWriter) ReadFrom(src io.Reader) (int64, error) {
if r, ok := mw.w.(io.ReaderFrom); ok {
return r.ReadFrom(src)
}
return io.Copy(struct{ io.Writer }{mw}, src)
}
This is unfortunate as myWriter satisfies the io.ReaderFrom interface, but it's implementation is no better than io.Copy (always incurring an allocation) in some circumstances.
In the case of io.CopyBuffer, I would argue that the user's expectation is that the buffer passed in is always used. It has the detriment of an extra copy, but I believe the cost of that is much lower than the allocation that is already saved by the user providing the buffer. It main benefit is that it avoids any shenanigans that occur because of inefficient implementations of io.ReaderFrom and io.WriterTo.
Alternative is to do anonymous struct value hack:
io.CopyBuffer(struct{ io.Writer }{dst}, struct{ io.Reader }{src}, buf)
But, this hack is not intuitive to most people.
Filed on behalf of @JKJI