simpleproof
simpleproof

Reputation: 65

How can I push bytes into a reader in Go?

I need to incrementally append bytes as I receive them to a buffer where I can read them again later. Something like this:

type TwoPassReader struct {
  someDataSource SomeDataReader
  secondPassReader io.Reader
}

func (r *TwoPassReader) Read(b []byte) (n int, err error) {
  n, err := r.someDataSource.Read(b)
  if err == nil {
    //XXX: this doesn't actually exist, right?
    bytesAppended, writeErr := r.secondPassReader.Write(b)
  }
  return n, err
}

func (r *) ReadSecondPass(b []byte) (n int, err error) {
  return r.secondPassReader.Read(b)
}

While the trivial answer for this would be to use bufio.Reader.Peek, I have a SomeDataReader object that I can't modify instead of a Reader. Is the best solution to just put the data into a []byte and return that when ReadSecondPass is called?

Upvotes: 4

Views: 1774

Answers (2)

justinas
justinas

Reputation: 6867

io.Reader is just an interface. We can't see what you're assigning to that struct field (if anything), but a bytes.Buffer would probably be the correct type to use here.

Upvotes: 1

peterSO
peterSO

Reputation: 166925

Something like this?

package main

import (
    "bytes"
    "io"
)

type TwoPassReader struct {
    firstPassReader  io.Reader
    secondPassBuffer io.ReadWriter
}

func NewTwoPassReader(firstPass io.Reader) *TwoPassReader {
    return &TwoPassReader{
        firstPassReader:  firstPass,
        secondPassBuffer: bytes.NewBuffer(nil),
    }
}

func (r *TwoPassReader) Read(b []byte) (n int, err error) {
    n1, err1 := r.firstPassReader.Read(b)
    n2, err2 := r.secondPassBuffer.Write(b[:n1])
    if err2 != nil {
        return n2, err2
    }
    return n1, err1
}

func (r *TwoPassReader) ReadSecondPass(b []byte) (n int, err error) {
    return r.secondPassBuffer.Read(b)
}

func main() {
}

Upvotes: 2

Related Questions