Temporary Files and Directories
os.CreateTemp and os.MkdirTemp for creating temporary files and directories, deferred cleanup, and t.TempDir in tests.
os.CreateTemp and os.MkdirTemp create temporary files and directories with unique, non-colliding names. They are the safe replacement for manual temp-file construction, which is vulnerable to race conditions.
os.CreateTemp creates a new file in the system temp directory (or a specified dir) with a unique name built from the given pattern. The returned *os.File is open for reading and writing. Clean up with os.Remove when done.
package main
import (
"fmt"
"os"
)
func main() {
// "" uses os.TempDir(); the name will be something like /tmp/example-1234567890
f, err := os.CreateTemp("", "example-")
if err != nil {
panic(err)
}
defer os.Remove(f.Name()) // clean up on exit
defer f.Close()
fmt.Println("temp file:", f.Name())
_, err = f.WriteString("temporary content\n")
if err != nil {
panic(err)
}
}os.MkdirTemp creates a temporary directory. Use it when you need a temporary workspace for multiple files. Clean up the whole tree with os.RemoveAll when done.
package main
import (
"fmt"
"os"
"path/filepath"
)
func main() {
dir, err := os.MkdirTemp("", "workspace-")
if err != nil {
panic(err)
}
defer os.RemoveAll(dir) // clean up entire directory
fmt.Println("temp dir:", dir)
// Create files inside the temp directory
p := filepath.Join(dir, "data.txt")
err = os.WriteFile(p, []byte("hello"), 0600)
if err != nil {
panic(err)
}
}In tests, use t.TempDir() instead of os.MkdirTemp. It returns a unique directory that the test runner removes automatically when the test completes - no manual cleanup needed.
package mypackage_test
import (
"os"
"path/filepath"
"testing"
)
func TestWriteConfig(t *testing.T) {
dir := t.TempDir() // cleaned up automatically after the test
cfg := filepath.Join(dir, "config.json")
err := os.WriteFile(cfg, []byte(`{"debug":true}`), 0600)
if err != nil {
t.Fatal(err)
}
// test logic that reads from cfg...
}In production
Always clean up temp files and directories, preferably with defer immediately after creation - a crash or early return without the defer running leaves them on disk. Temp files created by os.CreateTemp are not deleted on process exit. In tests, t.TempDir() is always preferable to manual os.MkdirTemp + defer os.RemoveAll - the test runner handles cleanup even if the test panics. When writing to a temp file and then renaming it over a real file (atomic write pattern), create the temp file in the same directory as the target so the rename stays on the same filesystem - cross-device renames fail with EXDEV. Set restrictive permissions (0600 for files, 0700 for directories) on temp paths that contain sensitive data; os.TempDir() is world-readable on Linux by default.
Enjoyed this? Get more essays on software craft delivered to your inbox.
Subscribe free