🎓 A1Learner
🔍
0 of 55 lessons completed

Zig Defer

Defer schedules a statement to run when the current scope ends. A scope is a block of code between braces, such as the body of main.

A deferred line runs after the lines that follow it

The defer is written between the start and end prints. The output order shows it still runs last.

const std = @import("std");

pub fn main() !void {
    const out = std.io.getStdOut().writer();
    try out.print("start\n", .{});
    defer out.print("deferred\n", .{}) catch {};
    try out.print("end\n", .{});
}

Defers run in reverse order

Two defers are written, first and then second. The output shows second runs before first, which proves the reverse order.

const std = @import("std");

pub fn main() !void {
    const out = std.io.getStdOut().writer();
    defer out.print("first defer\n", .{}) catch {};
    defer out.print("second defer\n", .{}) catch {};
    try out.print("body\n", .{});
}

A defer runs when its own block ends

This defer sits inside an inner block marked by braces. It runs as that block ends, before the line after the block.

const std = @import("std");

pub fn main() !void {
    const out = std.io.getStdOut().writer();
    {
        defer out.print("inner defer\n", .{}) catch {};
        try out.print("inner body\n", .{});
    }
    try out.print("after block\n", .{});
}

Example

const std = @import("std");

pub fn main() !void {
    const out = std.io.getStdOut().writer();
    try out.print("begin\n", .{});
    defer out.print("cleanup A\n", .{}) catch {};
    defer out.print("cleanup B\n", .{}) catch {};
    {
        defer out.print("inner cleanup\n", .{}) catch {};
        try out.print("inner work\n", .{});
    }
    try out.print("end work\n", .{});
}

Key points

  • Defer: defer writes a statement now and runs it later, when its scope ends.
  • Normal flow: the lines after a defer still run before the deferred statement.
  • Order: deferred statements run last in, first out, so the last defer written runs first.
  • Scope: a defer placed inside an inner block runs when that inner block ends.
  • Cleanup: defer is often used to release something right after it is created, so the release is not forgotten.

In this example, begin prints first and the inner block prints inner work, then its own defer runs inner cleanup as the block ends. The main body then prints end work, and the two outer defers run in reverse order, cleanup B before cleanup A.

Note

defer runs at the end of a scope in Zig, not after a set amount of time.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

A scope writes defer for cleanup X first and defer for cleanup Y second. When the scope ends, which cleanup runs first?