Skip to content

Instantly share code, notes, and snippets.

@hlubek
Created November 21, 2022 17:05
Show Gist options
  • Save hlubek/419e4db42393adb5eb21d51c246b11c8 to your computer and use it in GitHub Desktop.
Save hlubek/419e4db42393adb5eb21d51c246b11c8 to your computer and use it in GitHub Desktop.
A reader that buffers what it read and can be "recycled" to read again from the beginning
type recyclableReader struct {
originalReader io.Reader
teeReader io.Reader
buffer *bytes.Buffer
}
func newRecyclableReader(file io.Reader) *recyclableReader {
buffer := new(bytes.Buffer)
teeReader := io.TeeReader(file, buffer)
return &recyclableReader{
originalReader: file,
teeReader: teeReader,
buffer: buffer,
}
}
func (s *recyclableReader) Read(p []byte) (n int, err error) {
return s.teeReader.Read(p)
}
// recycle the reader to be read again with buffered data and unread data of the original reader
func (s *recyclableReader) recycle() {
prevBuffer := s.buffer
prevReader := s.originalReader
s.originalReader = io.MultiReader(prevBuffer, prevReader)
s.buffer = new(bytes.Buffer)
s.teeReader = io.TeeReader(s.originalReader, s.buffer)
}
// unwrap returns an unbuffered reader (cannot be recycled again)
func (s *recyclableReader) unwrap() io.Reader {
return s.originalReader
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment