The io package in Golang

The io package in Go provides input-output primitives as well as interfaces to them. It is one of the most essential packages in all of Golang. In this post, we are going to take a look at what this package offers.

Fundamental types

The io package provides two very fundamental types the Reader and Writer. The reader provides a function that simply reads bytes from streams. The writer is just the opposite.

The writer writes to the underlying stream of bytes.

These two interfaces compose to create many higher-level abstractions in this package.

Copying data using io package

Now we will see how the io package provides copying functions.

package main

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

func main() {
	r := strings.NewReader("Hello it is a string")

	_, e := io.Copy(os.Stdout, r)
	CheckError(e)
	// Hello it is a string
}

func CheckError(e error) {
	if e != nil {
		fmt.Println(e)
	}
}

The io.Copy function takes a reader and copies the data from source to destination.

The Copybuffer function takes a buffer and copies it using it. The buffered copying allows for more controlled copying rather than a direct one.

The copyN function is similar but it only copies up to Nth byte.

Reading data using io package

The io package has functions that can be used to read data from a reader. Here are the functions.

The ReadAtLeast function reads at least to the limit provided. It takes a buffer to do that. If the buffer is smaller or larger then it throws an error.

package main

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

func main() {
	r := strings.NewReader("Read this string")

	buf := make([]byte, 20)
	_, err := io.ReadAtLeast(r, buf, 4)
	CheckError(err)

	fmt.Println(string(buf))

	buf = make([]byte, 2)
	_, err = io.ReadAtLeast(r, buf, 4)
	CheckError(err)

	fmt.Println(string(buf))

	buf = make([]byte, 20)
	_, err = io.ReadAtLeast(r, buf, 20)
	CheckError(err)

	fmt.Println(string(buf))
}

func CheckError(e error) {
	if e != nil {
		fmt.Println(e)
	}
}
Go Read Atleast
Go ReadAtleast

The ReadFull function will read it completely up to the size of the buffer.

Golang io Package Pipe() Method

The pipe method returns a reader and a writer. They are synchronous which means even when using goroutines it will work perfectly. Here is an example.

package main

import (
	"bytes"
	"fmt"
	"io"
)

func main() {
	r, w := io.Pipe()

	go func() {
		fmt.Fprint(w, "Here are some text")
		w.Close()
	}()

	buf := new(bytes.Buffer)
	buf.ReadFrom(r)
	fmt.Print(buf.String()) // Here are some text
}

The WriteString() method

The io package WriteString() is a utility method. It takes a string and a writer and puts it into the stream. It is a simple function. Here is an example using it.

package main

import (
	"io"
	"os"
)

func main() {
	// write to stdout
	io.WriteString(os.Stdout, "Hello, World!") // Hello, World!
}