How to convert [] byte to io. In Go Reader?

Posted by phonydream on Wed, 29 Dec 2021 06:48:56 +0100

Original link: [how to convert [] byte into IO in Go Reader?] ( https://mp.weixin.qq.com/s/nF...)

See a problem on stackoverflow. The subject makes a network request, and the interface returns [] byte. If you want to convert it to io Reader, what do you need to do?

This problem is not complicated to solve. It can be easily converted into success with a few lines of code. Not only that, it can also be converted back through a few lines of code.

Now let me blow it to you slowly. First, look at two pieces of code directly.

[] byte to io Reader

package main

import (
    "bytes"
    "fmt"
    "log"
)

func main() {
    data := []byte("Hello AlwaysBeta")

    // byte slice to bytes.Reader, which implements the io.Reader interface
    reader := bytes.NewReader(data)

    // read the data from reader
    buf := make([]byte, len(data))
    if _, err := reader.Read(buf); err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(buf))
}

Output:

Hello AlwaysBeta

This code first converts the [] byte data into the reader, then reads the data from the reader and prints it out.

io.Reader to [] byte

package main

import (
    "bytes"
    "fmt"
    "strings"
)

func main() {
    ioReaderData := strings.NewReader("Hello AlwaysBeta")

    // creates a bytes.Buffer and read from io.Reader
    buf := &bytes.Buffer{}
    buf.ReadFrom(ioReaderData)

    // retrieve a byte slice from bytes.Buffer
    data := buf.Bytes()

    // only read the left bytes from 6
    fmt.Println(string(data[6:]))
}

Output:

AlwaysBeta

This code first creates a reader, then reads the data to buf, and finally prints out.

The above two codes are [] byte and Io The process of reader conversion. Comparing these two pieces of code, it is not difficult to find that there is a figure of NewReader. And it plays a key role in the conversion process.

So the question is, what is this NewReader? Next, we explore the source code.

Source code analysis

The IO package of Go provides the most basic IO interface, where io Reader and Io The two interfaces of writer are the most critical. Many native structures are developed around these two interfaces.

Let's talk about these two interfaces:

Reader interface

io.Reader represents a reader that reads data from a resource to a transport buffer. In the buffer, data can be streamed and used.

The interface is defined as follows:

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

The Read() method reads len(p) bytes into p. It returns the number of bytes read, n, and the error message when the error occurred.

For example:

package main

import (
    "fmt"
    "io"
    "os"
    "strings"
)

func main() {
    reader := strings.NewReader("Clear is better than clever")
    p := make([]byte, 4)

    for {
        n, err := reader.Read(p)
        if err != nil {
            if err == io.EOF {
                fmt.Println("EOF:", n)
                break
            }
            fmt.Println(err)
            os.Exit(1)
        }
        fmt.Println(n, string(p[:n]))
    }
}

Output:

4 Clea
4 r is
4  bet
4 ter
4 than
4  cle
3 ver
EOF: 0

This code continuously reads data from the reader, 4 bytes at a time, and then prints out until the end.

The last returned n value may be less than the buffer size.

Writer interface

io.Writer represents a writer that reads data from a buffer and writes data to a target resource.

type Writer interface {
   Write(p []byte) (n int, err error)
}

The Write method writes len(p) bytes from p to the object data stream. It returns the number of bytes written from p, n, and the error information returned when an error occurs.

For example:

package main

import (
    "bytes"
    "fmt"
    "os"
)

func main() {
    // Create Buffer scratch space and write a string to Buffer
    // Use io Write method of writer
    var buf bytes.Buffer
    buf.Write([]byte("hello world , "))

    // Use Fprintf to splice a string into Buffer
    fmt.Fprintf(&buf, " welcome to golang !")

    // Output the contents of the Buffer to the standard output device
    buf.WriteTo(os.Stdout)
}

Output:

hello world ,  welcome to golang !

bytes.Buffer is a structure type used to temporarily store written data, which implements io The Write method of the writer interface.

WriteTo method definition:

func (b *Buffer) WriteTo(w io.Writer) (n int64, err error)

The first parameter of the WriteTo method is Io Writer interface type.

Conversion principle

Let's go back to the conversion problem at the beginning of the article.

As long as an instance implements the interface io The method Read() in reader satisfies the interface io Reader.

Both the bytes and strings packages implement the Read() method.

// src/bytes/reader.go

// NewReader returns a new Reader reading from b.
func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} }
// src/strings/reader.go

// NewReader returns a new Reader reading from s.
// It is similar to bytes.NewBufferString but more efficient and read-only.
func NewReader(s string) *Reader { return &Reader{s, 0, -1} }

When calling NewReader, the corresponding T.Reader type will be returned, and they are all through io Reader extension, so the conversion is realized.

summary

In the development process, some IO operations can not be avoided, including printout, file reading and writing, network connection, etc.

In Go language, a series of standard libraries are also provided to deal with these operations, which are mainly encapsulated in the following packages:

  • IO: basic IO operation interface.
  • io/ioutil: encapsulates some practical IO functions.
  • fmt: implements IO format operation.
  • bufio: implements buffered IO.
  • net.Conn: network reading and writing.
  • os.Stdin,os.Stdout: system standard input and output.
  • os.File: system file operation.
  • bytes: byte related IO operations.

Except io Reader and Io In addition to writer, the IO package also encapsulates many other basic interfaces, such as ReaderAt, WriterAt, ReaderFrom and WriterTo, which will not be introduced here. This part of the code is not complex, it is easy to read, and it can deepen the understanding of the interface. I recommend you to have a look.

Well, that's all for this article. Pay attention to me and take you through the question to read the Go source code.

Recommended reading:

Warm recommendation:

  • Computer classic books (including download method)
  • Technology blog : hard core back-end technology dry goods, including Python, Django, Docker, Go, Redis, ElasticSearch, Kafka, Linux, etc.
  • Go programmer : Go learning roadmap, including a series of resources such as basic column, advanced column, source code reading, practical development, interview question brushing, required reading list, etc.
  • Summary of interview questions : including Python, Go, Redis, MySQL, Kafka, data structure, algorithm, programming, network and other frequently asked questions.

Reference article:

Topics: Go io