Defer & Errdefer
Defer
Runs a statement when the enclosing scope exits — whether by normal return, early return, or error propagation.
tape
fn read_file(path: string) -> string or IoError {
let f = open(path) or return;
defer close(f);
// even if this fails and returns early, close(f) runs
let data = read_all(f) or return;
return data;
}Multiple defers
Defers execute in reverse order (LIFO):
tape
fn setup() {
let a = acquire_a();
defer release_a(a);
let b = acquire_b();
defer release_b(b);
// on scope exit: release_b runs first, then release_a
}Errdefer
Runs only if the scope exits via an error return:
tape
fn init() -> Resource or Error {
let mem = allocate(1024) or return;
errdefer free(mem); // only runs if we return an error below
let handle = open_device() or return;
// if open_device fails, mem is freed
// if it succeeds, mem is NOT freed (caller owns it)
return Resource { mem: mem; handle: handle; };
}Defer vs errdefer
| Runs on success | Runs on error | |
|---|---|---|
defer | Yes | Yes |
errdefer | No | Yes |
Use defer for cleanup that always happens (close files, release locks). Use errdefer for cleanup that only happens on the failure path (free partially-constructed resources).
Last modified: