In this article, we will walk through some examples of converting from an io.Reader to a string in Go.
What is io.Reader()
and strings.NewReader()
in Golang
Reader is the interface that wraps the basic Read method.
Read reads up to len(p)
bytes into p
. It returns the number of bytes read (0 <= n <= len(p)
) and any error encountered. Even if Read returns n < len(p)
, it may use all of p
as scratch space during the call. If some data is available but not len(p)
bytes, Read conventionally returns what is available instead of waiting for more.
type Reader interface {
Read(p []byte) (n int, err error)
}
In this tutorial, we will use the strings.NewReader()
function to create an io.Reader()
func NewReader(s string) *Reader
: NewReader returns a new Reader reading from s. It is similar to bytes.NewBufferString
but more efficient and read-only. NewBufferString creates and initializes a new Buffer using string s as its initial contents. It is intended to prepare a buffer to read an existing string.
Example 1: Convert from an io.Reader
to a string using strings.Builder()
We can use a strings.Builder()
and io.Copy()
function to convert from an io.Reader
to a string. A Builder is used to efficiently build a string using Write methods. It minimizes memory copying. The zero value is ready to use. Do not copy a non-zero Builder.
type Builder struct {
// contains filtered or unexported fields
}
func Copy(dst Writer, src Reader) (written int64, err error)
: Copy copies from src to dst until either EOF is reached on src or an error occurs. It returns the number of bytes copied and the first error encountered while copying if any.
Here is an example of using strings.Builder()
to generate a string from an io.Reader()
:
package main
import (
"fmt"
"io"
"log"
"strings"
)
func main() {
reader := strings.NewReader("This is GoLinuxCloud!")
buf := new(strings.Builder)
_, err := io.Copy(buf, reader)
if err != nil {
log.Fatal(err)
}
// check errors
fmt.Println(buf.String())
}
Output:
This is GoLinuxCloud!
Example 2: Convert from io.Reader
to a string using ReadFrom()
function
The example below illustrates how to use the Buffer
struct and ReadFrom()
function to convert from an io.Reader
to a string:
type Buffer struct {
// contains filtered or unexported fields
}
A Buffer is a variable-sized buffer of bytes with Read and Write methods. The zero value for Buffer is an empty buffer ready to use.
func (*Buffer) ReadFrom
: ReadFrom reads data from r until EOF and appends it to the buffer, growing the buffer as needed. The return value n is the number of bytes read. Any error except io.EOF encountered during the read is also returned. If the buffer becomes too large, ReadFrom will panic with ErrTooLarge.
package main
import (
"bytes"
"fmt"
"strings"
)
func main() {
reader := strings.NewReader("This is GoLinuxCloud!")
buf := new(bytes.Buffer)
buf.ReadFrom(reader)
str := buf.String()
fmt.Println(str)
}
Output:
This is GoLinuxCloud!
Example 3: Convert from io.Reader
to string using io.ReadAll()
function
func ReadAll(r Reader) ([]byte, error)
: ReadAll reads from r until an error or EOF and returns the data it read. A successful call returns err == nil, not err == EOF. Because ReadAll is defined to read from src until EOF, it does not treat an EOF from Read as an error to be reported.
In this example, we will use the io.ReadAll()
function to reads from the io.Reader()
and return a string:
package main
import (
"fmt"
"io"
"log"
"strings"
)
func main() {
reader := strings.NewReader("This is GoLinuxCloud!")
if b, err := io.ReadAll(reader); err == nil {
fmt.Println(string(b))
} else {
log.Fatal(err)
}
}
Output:
This is GoLinuxCloud!
Noted that, for Go version < v1.15, we can use the built-in package ioutil
instead of the io
package.
Example 4: Convert from an io.Reader
to a byte slice and convert it to a string
Another way would be to always use []byte
instead of a string. We already have an article about how to convert from an io.Reader to a byte slice. Let’s see an example of how we can convert an io.Reader
 to a byte slice in Go using the Buffer type:
package main
import (
"bytes"
"fmt"
"strings"
)
func main() {
reader := strings.NewReader("This is GoLinuxCloud!")
// a bytes.Buffer and read from io.Reader
buf := new(bytes.Buffer)
buf.ReadFrom(reader)
// get a byte slice from bytes.Buffer
data := buf.Bytes()
// convert byte slice to string
fmt.Println(string(data[:10]))
}
Output:
This is Go
Summary
The examples above are the most efficient way to convert the entire stream to a string object. In this example, we use the strings.NewReader()
as the implementation of io.Reader()
interface. With the explained methods, we can apply them to any other io.Reader()
implementation to convert it to a string.
References
https://pkg.go.dev/strings#NewReader
https://pkg.go.dev/bytes#Buffer
https://pkg.go.dev/io#ReadAll