#Working with Temporary Files and Directories in Go 1.11
Go provides excellent built-in support for creating temporary files and directories
using the TempFile and TempDir functions within the os package.
The temporary files and directories created from these function calls are globally unique and this is awesome as it simplifies the way we handle hundreds or even thousands of files within our Go programs.
In this tutorial, we’ll be looking at how you can use these within your own Go
programs and some potential use cases. Note that while ioutil was historically used,
modern Go (1.16+) recommends using the os package directly for these operations.
Creating Temporary Files
Let’s start off by looking at the new TempFile function. Let’s say we were
creating an object recognition system that pulled in thousands of pictures of
cars and used them as training sets.
For each of the cars we pull in, we’ll want to create a temporary file with a unique name that we don’t necessarily care about.
package main
import (
"fmt"
"log"
"os"
)
func main() {
// we call os.CreateTemp which returns either a file
// or an error.
// we specify the directory we want to create these temp files in
// for this example we'll use `car-images`, and we'll define
// a pattern which will be used for naming our car images
// in this case car-*.png
file, err := os.CreateTemp("car-images", "car-*.png")
if err != nil {
log.Fatal(err)
}
// We can choose to have these files deleted on program close
defer os.Remove(file.Name())
// We can then have a look and see the name
// of the image that has been generated for us
fmt.Println(file.Name())
}
If we then try to run this in our console, we should see the following output:
$ go run main.go
car-images/car-982382640.png
This has automatically replaced the * character within our defined car-*.png
pattern with a random, globally-unique number.
Writing to Temporary Files
If we want to write to these temporary files, we can do so using the Write
function like so:
package main
import (
"fmt"
"log"
"os"
)
func main() {
// we call os.CreateTemp which returns either a file
// or an error.
// we specify the directory we want to create these temp files in
// for this example we'll use `car-images`, and we'll define
// a pattern that will be used for all of our individual image filenames
// in this case we'll use 'car-*.png'
file, err := os.CreateTemp("car-images", "car-*.png")
if err != nil {
log.Fatal(err)
}
// We can choose to have these files deleted on program close
defer os.Remove(file.Name())
if _, err := file.Write([]byte("hello world\n")); err != nil {
log.Fatal(err)
}
data, err := os.ReadFile(file.Name())
// if our program was unable to read the file
// log the error and exit
if err != nil {
log.Fatal(err)
}
// if it was successful in reading the file then
// print out the contents as a string
fmt.Print(string(data))
}
This will write Hello World\n to our temporary file, and then attempt to read
in the contents of that file using the ioutil.ReadFile() function. When we run
this, we should see the following output:
$ go run main.go
hello world
Generating Temporary Directories
Now that we’ve covered temporary files, let’s have a look at generating temporary directories. This could be useful if we wanted to extend our object recognition system further and generate directories containing distinct objects and cars within them.
Let’s have a look at a simple, practical example as to how we can use this. We’ll be extending our existing program from above to create a temporary directory in which our temporary car files will exist:
package main
import (
"fmt"
"log"
"os"
)
func main() {
tempDir, err := os.MkdirTemp("", "cars-")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(tempDir)
file, err := os.CreateTemp(tempDir, "car-*.png")
if err != nil {
log.Fatal(err)
}
defer os.Remove(file.Name())
// This will print out the full name and path of our image
fmt.Println(file.Name())
if _, err := file.Write([]byte("hello world\n")); err != nil {
log.Fatal(err)
}
data, err := os.ReadFile(file.Name())
// if our program was unable to read the file
// log the error and exit
if err != nil {
log.Fatal(err)
}
// if it was successful in reading the file then
// print out the contents as a string
fmt.Print(string(data))
}
When we go to run this, we should see our globally unique directory being created and our globally unique filename appended to the end of that directory:
$ go run main.go
/var/folders/3x/5g0pww953x54mq7rjttr5f880000gn/T/cars-396489778/car-860960233.png
hello world
Conclusion
Awesome, in this tutorial, we looked at how we could use the MkdirTemp and
CreateTemp functions from the os package to create temporary files and directories.
Your opinion matters in making these tutorials the best they can be, if you have any ideas/suggestions as to how I can improve these tutorials then I would love to hear them in the suggestions box below!
Note - If you want to keep track of when new Go articles are posted to the site, then please feel free to follow me on twitter for all the latest news: @Elliot_F.
For further learning on file operations, check out Reading and Writing Files in Go and working with directories in Go.
Related Reading:
Continue Learning
Reading And Writing To Files in Go
In this tutorial, we are going to look at how you can read and write files on your local filesystem using Go
Go Project Structure Best Practices
In this article, we are going to look at some of the best practices that you should consider when structuring your Go applications.
Go Pointers Tutorial
In this tutorial, we are going to be covering pointers in Go and how you can use them within your own Go programs. We'll be covering the best practices and we'll be covering some of the most common use-cases for pointers.
Improving Your Go Development Workflow With Git Hooks
In this article, we are going to be taking a look at how you can improve your Go development workflow through the use of git hooks that automatically format and lint your Go code