4

How to use the io.Reader interface

 3 years ago
source link: https://yourbasic.org/golang/io-reader-interface-explained/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

How to use the io.Reader interface

yourbasic.org/golang
teddy-bear-reading.jpg

Basics

The io.Reader interface represents an entity from which you can read a stream of bytes.

type Reader interface {
        Read(buf []byte) (n int, err error)
}

Read reads up to len(buf) bytes into buf and returns the number of bytes read – it returns an io.EOF error when the stream ends.

The standard library provides numerous Reader implementations (including in-memory byte buffers, files and network connections), and Readers are accepted as input by many utilities (including the HTTP client and server implementations).

Use a built-in reader

As an example, you can create a Reader from a string using the strings.Reader function and then pass the Reader directly to the http.Post function in package net/http. The Reader is then used as the source for the data to be posted.

r := strings.NewReader("my request")
resp, err := http.Post("http://foo.bar",
	"application/x-www-form-urlencoded", r)

Since http.Post uses a Reader instead of a []byte it’s trivial to, for instance, use the contents of a file instead.

Read directly from a byte stream

You can use the Read function directly (this is the least common use case).

r := strings.NewReader("abcde")

buf := make([]byte, 4)
for {
	n, err := r.Read(buf)
	fmt.Println(n, err, buf[:n])
	if err == io.EOF {
		break
	}
}
4 <nil> [97 98 99 100]
1 <nil> [101]
0 EOF []

Use io.ReadFull to read exactly len(buf) bytes into buf:

r := strings.NewReader("abcde")

buf := make([]byte, 4)
if _, err := io.ReadFull(r, buf); err != nil {
	log.Fatal(err)
}
fmt.Println(buf)

if _, err := io.ReadFull(r, buf); err != nil {
	fmt.Println(err)
}
[97 98 99 100]
unexpected EOF

Use ioutil.ReadAll to read everything:

r := strings.NewReader("abcde")

buf, err := ioutil.ReadAll(r)
if err != nil {
	log.Fatal(err)
}
fmt.Println(buf)
[97 98 99 100 101]

Buffered reading and scanning

The bufio.Reader and bufio.Scanner types wrap a Reader creating another Reader that also implements the interface but provides buffering and some help for textual input.

In this example we use a bufio.Scanner to count the number of words in a text.

const input = `Beware of bugs in the above code;
I have only proved it correct, not tried it.`

scanner := bufio.NewScanner(strings.NewReader(input))
scanner.Split(bufio.ScanWords) // Set up the split function.

count := 0
for scanner.Scan() {
    count++
}
if err := scanner.Err(); err != nil {
    fmt.Println(err)
}
fmt.Println(count)
16

Share:             


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK