Scope Guards
A scope guard uses the Drop trait to run cleanup code automatically when a
scope exits, even during unwinding.
use scopeguard::{ScopeGuard, guard}; use std::fs::{self, File}; use std::io::Write; fn download_successful() -> bool { // [...] true } fn main() { let path = "download.tmp"; let mut file = File::create(path).expect("cannot create temporary file"); // Set up cleanup immediately after file creation let cleanup = guard(path, |path| { println!("download failed, deleting: {:?}", path); let _ = fs::remove_file(path); }); writeln!(file, "partial data...").unwrap(); if download_successful() { // Download succeeded, keep the file let path = ScopeGuard::into_inner(cleanup); println!("Download '{path}' complete!"); } // Otherwise, the guard runs and deletes the file }
-
This example models a download workflow. We create a temporary file first, then use a scope guard to ensure that the file is deleted if the download fails.
-
The
scopeguardcrate allows you to conveniently define a single-useDrop-based cleanup without defining a custom type with a customDropimplementation. -
The guard is created directly after creating the file, so even if
writeln!()fails, the file will still be cleaned up. This ordering is essential for correctness. -
The
guard()creates aScopeGuardinstance. It a user-defined value (in this case,path) and the cleanup closure that later receives this value. -
The guard’s closure runs on scope exit unless it is defused with
ScopeGuard::into_inner(removing the value so the guard does nothing on drop). In the success path, we callinto_innerso the guard will not delete the file. -
A scope guard is similar to the
deferfeature in Go. -
This pattern is ideal for “cleanup on failure” scenarios, where a cleanup should run by default unless a success path is explicitly taken.
-
This pattern is also useful when you don’t control the cleanup strategy of the resource object. In this example,
File::drop()closes the file but does not delete it, and we can’t change the standard library to delete the file instead (nor should we, it is not a good idea anyway). -
The
scopeguardcrate also supports cleanup strategies via theStrategytrait. You can choose to run the guard on unwind only, or on success only, not just always.