A guide to working with text files in Go

As a programming language, Go has a wide range of built-in features, including the ability to create, read, and write files such as text files (.txt).


Files are important parts of our daily life in the modern world. Text files are useful for storing human-readable structured data without using external software or databases.

If you’re wondering how to get started manipulating text files in Go, this article is for you.


The bufio package in Go

The bufio package, which is part of the Go standard library, is used for buffered input and output operations, hence its name. The bufio package relies on the io.Reader and io.Writer interfaces, which are widely used in the implementation of the majority of standard Go packages.

The bufio package goes a step further by implementing buffering, which makes it useful for I/O operations involving textual data.

To use the bufio package in your program, you need to import it along with other packages.

import (
"fmt"
"bufio"
)

When you first started with Go, you probably heard that it has everything you could possibly need as a programmer. For direct communication with your operating system, there is a package called bone which provides platform-independent functions.

The bone and bufio packages make manipulating text files incredibly simple.

Although the vast majority of bone The functions in the package are Unix-like, they all use the Go style of error handling, which makes it easier to read error messages and debug code.

So how do you handle files containing text in Go?

How to read data from a text file

To read data from text files, you must call the bone packages Open() which accepts the name of the file to read as a parameter. Another way to get the file is to use the open file() function.

The major difference between Open() and open file() is in their implementation. Open() opens a file in read-only mode (with the O_RDONLY flag), while open file() gives more flexibility by accepting three parameters, namely:

  • File name
  • File Open Mode: Valid file open modes are shown in the table below.
    Flag Meaning
    O_RDONLY Open the file in read-only mode
    O_WRONLY Open file in write-only mode
    O_RDWR Open file in read-write mode
    O_APPEND Appends data to file when writing
    O_CREATE Create a new file if one does not exist
    O_EXCL Used with O_CREATE, to indicate that the file should only be created if it does not exist
    O_SYNC Open file for synchronous I/O
    O_TRUNC Truncate the file on opening, if possible
  • File Permissions: Same as file permission bits in Linux used to specify file access rules, for example, 0777 to grant read, write, and execute permissions to all types of users .

The code below shows how to read data from a text file into Go using os.Open()and To analyse() which in this case runs in a Go for loop.

package main
import (
"bufio"
"fmt"
"log"
"os"
)
/**
CONTENT OF THE "testfile.txt" file.
lorem ipsum dolor sit amet
LOREM IPSUM DOLOR SIT AMET
Lorem ipsum dolor sit amet
Lorem Ipsum Dolor Sit Amet
lOREM iPSUM dOLOR sIT aMET
LoReM IpSuM DoLoR SiT AmEt
*/
func main() {
file, err := os.Open("testfile.txt")
// file, err = os.OpenFile("testfile.txt", os.O_RDONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
fmt.Println("File opened successfully. Now reading file contents line by line:")
// create scanner from the file to read text from
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}

When you run the above code with go run filename.goit produces the output below:

If you only pass the file name and not the path to the Open() Where open file() for read operations, Go assumes the file is in the current directory and returns an error if it can’t find it. You must pass the file path if you need to work with files outside the current directory.

How to write data to a text file

The bufio package provides buffering Writer interface that stores bytes of data and writes them to a file using a Flush() function.

The next code example is a continuation of the one for reading a file. In this example, data is written to the testfile.txt using the O_WRONLY and O_APPEND flags.

Add the following lines of code to the above program, before the closing brace of the main() function:


file, err = os.OpenFile("testfile.txt", os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
fmt.Println("File opened successfully, Now preparing to write data to file...")
textWriter := bufio.NewWriter(file)
_, err = textWriter.WriteString("-This is a new text added to the file.")
if err != nil {
log.Fatal(err)
}
textWriter.Flush()
fmt.Println("Data written to file successfully...")

The output of your complete program should look like this:

When you open the testfile.txt file, you will also see the new line added to the end of the file, just like the image below:

File management in Go is easy

Go lets you work with a variety of files, not just text files. There are many additional built-in libraries and functions for working with different types of data from files, including JSON and CSV.

To see how they behave differently depending on the situation, you can experiment with the different file flags and permissions available for use with open file().

Calvin W. Soper