Reader
Reader
Reader is any type that implements the
Read
method.The io.Reader interface represents an entity from which you can read a stream of bytes. A reader, represented by interface io.Reader, reads data from some source into a transfer buffer where it can be streamed and consumed
type Reader interface {
Read(p []byte) (n int, err error)
}
Things to note:
- Read reads up to len(p) bytes into p and returns the number of bytes read – it returns an io.EOF error when the stream ends.
- After a Read() call, n may be less then len(p)
- Upon error, Read() may still return n bytes in buffer p
- If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.
- A call to Read() that returns n=0 and err=nil does not mean EOF as the next call to Read() may return more data.
- When a Read() exhausts available data, a reader may return a non-zero n and err=io.EOF. However, depending on implementation, a reader may choose to return a non-zero n and err = nil at the end of stream. In that case, any subsequent reads must return n=0, err=io.EOF.
Question:
- What is the use of Reader?
You can read from a reader directly (this turns out to be the least useful use case):
p := make([]byte, 256) n, err := r.Read(p)
Example:
Method Read is designed to be called within a loop where, with each iteration, it reads a chunk of data from the source and places it into buffer p. This loop will continue until the method returns an io.EOF error.
package main
import (
"fmt"
"io"
"strings"
)
func main() {
r := strings.NewReader("abcde")
buf := make([]byte, 4)
for {
n, err := r.Read(buf)
fmt.Println(n, err, string(buf[:n]))
if err == io.EOF {
break
}
}
}
Output:
4 <nil> abcd
1 <nil> e
0 EOF
Example that shows the contents in the transfer buffer:
package main
import (
"fmt"
"io"
"strings"
)
func main() {
r := strings.NewReader("abcdef")
buf := make([]byte, 4)
for {
n, err := r.Read(buf)
fmt.Println(n, err, string(buf))
if err != nil {
if err == io.EOF {
fmt.Println(string(buf))
break
}
fmt.Println(err)
return
}
}
}
Output:
4 <nil> abcd
2 <nil> efcd
0 EOF efcd
efcd
Use io.ReadFull to read exactly len(buf) bytes into buf:
package main
import (
"fmt"
"io"
"log"
"strings"
)
func main() {
r := strings.NewReader("abcde")
buf := make([]byte, 4)
if _, err := io.ReadFull(r, buf); err != nil {
log.Fatal(err)
}
fmt.Println(string(buf))
if _, err := io.ReadFull(r, buf); err != nil {
fmt.Println(err)
}
}
Output:
abcd
unexpected EOF
Use ioutil.ReadAll to read everything:
package main
import (
"fmt"
"io/ioutil"
"log"
"strings"
)
func main() {
r := strings.NewReader("abcde")
buf, err := ioutil.ReadAll(r)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(buf))
}
Output:
abcde
Some examples of readers:
- If you open a file for reading, the object returned is an
os.File
, which is a Reader (it implements the Read method):var r io.Reader var err error r, err = os.Open("file.txt")
- You can also make a Reader from a normal string using
strings.NewReader
:var r io.Reader r = strings.NewReader("Read will return these bytes")
- The body data from an
http.Request
is a Reader:var r io.Reader r = request.Body
- A bytes.Buffer is a Reader:
var r io.Reader var buf bytes.Buffer r = &buf