Atomic file writes with temp and rename
Go
package main
import (
"fmt"
"os"
"path/filepath"
)
// WriteFileAtomic replaces path with data via a temp file and rename, so
// readers never observe a partially written file.
func WriteFileAtomic(path string, data []byte) error {
tmp, err := os.CreateTemp(filepath.Dir(path), "."+filepath.Base(path)+".*")
if err != nil {
return fmt.Errorf("create temp file: %w", err)
}
name := tmp.Name()
defer os.Remove(name) // clean up if the rename fails
if _, err := tmp.Write(data); err != nil {
tmp.Close()
return fmt.Errorf("write temp file: %w", err)
}
if err := tmp.Close(); err != nil {
return fmt.Errorf("close temp file: %w", err)
}
if err := os.Chmod(name, 0o644); err != nil {
return fmt.Errorf("chmod temp file: %w", err)
}
if err := os.Rename(name, path); err != nil {
return fmt.Errorf("rename temp file: %w", err)
}
return nil
}
func main() {
_ = WriteFileAtomic("settings.json", []byte(`{"theme":"dark"}`))
fmt.Println("saved settings.json")
}