Quite often, you'll need your program to work with data that is outside the codebase, and regularly this data will come in the form of files.
In this topic, you'll learn the basics of working with files – how to open, close, create and delete files using Go.
Open file
To start learning how to work with files, we will begin with opening an existing one. In Go, we can import the os package from the standard library to open a file in the read-only mode using the os.Open() function.
package main
import (
"log"
"os"
)
func main() {
// example of opening a file in the read-only mode
file, err := os.Open("test_file.txt")
if err != nil {
log.Fatal(err) // log the error into the terminal and exit the program
}
// closing the file
file.Close()
}The os.Open() function has one required parameter — name, which is the complete path of the file that you want to open. In this example, the name parameter has the value "test_file.txt": it supposes that test_file.txt is present in our current working directory.
If opening the file fails for any reason, the program will log the error into our terminal and immediately exit:
// Linux/macOS:
2022/03/20 15:33:32 open test_file.txt: no such file or directory
// Windows:
2022/03/20 15:33:32 open test_file.txt: The system cannot find the file specified.After we are done working with files, we always need to close them! Closing the file guarantees the safety of the data and prevents the program from further accessing the file. In Go, we can close files using the Close() function:
// close the file
file.Close()os.OpenFile
Apart from os.Open(), we can also use the os.OpenFile() function that lets us open files with additional options:
// opening a file using the os.O_RDONLY flag
file, err := os.OpenFile("test_file.txt", os.O_RDONLY, 0644)
if err != nil {
log.Fatal(err)
}The os.OpenFile() function has two additional parameters: the parameter that goes after the file name is the specified flag, and the last parameter is the permission mode perm. The permission mode will usually be 0644 when opening files in the read, write, or read-and-write mode, and 0666 when creating new files. You can find more information about permission modes on this page.
When opening a file withos.OpenFile(), you can choose one of these three flags:
| Opens the file in the read-only mode, just like |
| Opens the file in the write-only mode |
| Opens the file in the read-and-write mode |
You can combine these other flags using the '|' operator:
| Appends data to the end of the file |
| Creates the file in case it does not exist |
In the following example, we combine the os.O_WRONLY and os.O_APPEND flags:
// flags os.O_WRONLY and os.O_APPEND combined:
file, err := os.OpenFile("test_file.txt", os.O_WRONLY | os.O_APPEND, 0644)
if err != nil {
log.Fatal(err)
}After executing this block of code, the existing test_file.txt will be open, and we will have permission to append data to the end of this file.
Creating a new file
In certain cases, we need to create a file during the execution of our program. To create a new file in Go, we can use the os.Create() function: it creates a new file, or otherwise it truncates the file if we use it with the name of a file that already exists.
os.Create() creates a new file with the os.O_RDWR flag and the 0666 permission: this means that after creating the file, we will have the necessary permissions to work with it in the read-and-write mode.
// this creates a new file, or truncates the already existing file
file, err := os.Create("new_file.txt")
if err != nil {
log.Fatal(err)
}Remember that if you already have a file with some data and use os.Create() with the same name, the file data will be truncated! Be careful when using os.Create() and working with files that contain valuable data.
Another way to create a new file in Go is to use the os.OpenFile() function that we explored earlier. In this case, we need to specify the os.O_CREATE flag and the 0666 permission.
// this creates a new file using the os.O_CREATE flag and the 0666 permission
file, err := os.OpenFile("new_file.txt", os.O_CREATE, 0666)
if err != nil {
log.Fatal(err)
}Using os.OpenFile() with the os.O_CREATE flag will not truncate the file if it already exists, as opposed to os.Create(). In this case, nothing will happen to the existing file and the information will not be truncated.
Deleting a file
If we need to delete a file during the execution of our program, we can use the os.Remove() function.
The os.Remove() function accepts one argument — name, which is the path to the file name or empty directory. We can also adjust this argument to point to a specific location using the proper path syntax of our operating system.
// this deletes "new_file.txt" from our current working directory
err := os.Remove("new_file.txt")
if err != nil {
log.Fatal(err)
}If the file we're trying to delete doesn't exist, we will get the following error:
2022/03/20 15:34:37 remove new_file.txt: The system cannot find the file specified.If we try to delete a directory but the directory isn't empty, we will get the following error:
2022/03/20 15:35:01 remove test_directory: The directory is not empty.Occasionally, it might be useful to delete more than one file. For this, we can use the os.RemoveAll() function.
The os.RemoveAll() function accepts one argument — path. It will delete everything inside the specified path (files and folders).
// this deletes "test_directory" and all of its contents
err := os.RemoveAll("test_directory")
if err != nil {
log.Fatal(err)
}Summary
In this topic, you've learned the basics of working with files in Go: how to open and close files, how to create new ones and delete existing files.
When opening a file, os.Open() will always open the file in the read-only mode. If we want to open the file in the write-only or the read-and-write mode, we will have to use os.OpenFile() with the proper flags, according to our needs.
Remember to always close files using the Close() function as soon as you are done working with them! This way you can protect files with valuable data.
When creating a new file, we can use os.Create() that will create a new file or truncate the file if it already exists. We can also use os.OpenFile() with the os.O_CREATE flag and the 0666 permission to create a new file, without the risk of truncating an already existing file.
Last but not least: we can use os.Remove() to delete a single file or an empty directory, and os.RemoveAll() in case we need to delete multiple files or directories.