A Guide to Working With Text Files in Go

As a programming language, Go has a wide range of inbuilt features, including the ability to create, read, and write files like text (.txt) files.


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

If you’re wondering how you could begin manipulating text files in Go, this article is the right place for you.


The bufio Package in Go

The bufio package, which is a part of Go’s standard library, is used for buffered input and output operations, hence the name. The bufio package builds upon the io.Reader and io.Writer interfaces, which are extensively used in the implementation of the majority of Go’s standard packages.

The bufio package goes one step further by implementing buffering, making it useful for IO operations involving textual data.

To use the bufio package in your program, you should import it alongside other packages.

import (
"fmt"
"bufio"
)

You probably heard when you got started with Go that it comes with everything you could possibly need as a programmer. For direct communication with your operating system, there is a package called os that provides platform-independent functions.

The os and bufio packages make text file manipulation incredibly simple.

Although the vast majority of the os package’s functions are Unix-like, they all employ the Go style of error handling, which makes it simple to read error messages and debug code.

So, how do you manipulate files containing text in Go?

How to Read Data From a Text File

To read data from text files, you need to call the os package’s Open() function, which accepts the name of the file to be read as a parameter. Another method to get the file is by using the OpenFile() function.

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

  • File name
  • File open mode: The valid file open modes are shown in the table below.
    Flag Meaning
    O_RDONLY Opens the file in read-only mode
    O_WRONLY Opens the file in write-only mode
    O_RDWR Opens the file in read-write mode
    O_APPEND Appends data to the file when writing
    O_CREATE Creates a new file if none exists
    O_EXCL Used with O_CREATE, to indicate that the file should only be created if it doesn’t exist
    O_SYNC Opens file for synchronous I/O
    O_TRUNC Truncate the file on open, if possible
  • File permissions: Same as the file permission bits in Linux used for specifying file access rules, e.g., 0777 to grant read, write, and execute permissions to all user types.

The code below shows how to read data from a text file in Go using os.Open(), and Scan() 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 code above with go run filename.go, it produces the output shown below:

If you pass in just the file name and not the path to the Open() or OpenFile() function for read operations, Go assumes the file is in the present directory and returns an error if it doesn’t find it. You should pass in the path to the file if you need to work with files outside the current directory.

How to Write Data to a Text File

The bufio package provides a buffered Writer interface that stores bytes of data and writes them to a file with the help of a Flush() function.

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

Add the following lines of code to the program above, before the closing curly 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 appended at the end of the file just like the image below:

File Handling in Go Is Easy

Go allows you to work with a variety of files, not just text files. There are numerous additional inbuilt 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 various flags and file permissions that are available for use with OpenFile().

We use cookies to give you the best experience.