defer

Executes an expression unconditionally at scope exit.

test_defer.zig

  1. const std = @import("std");
  2. const expect = std.testing.expect;
  3. const print = std.debug.print;
  4. fn deferExample() !usize {
  5. var a: usize = 1;
  6. {
  7. defer a = 2;
  8. a = 1;
  9. }
  10. try expect(a == 2);
  11. a = 5;
  12. return a;
  13. }
  14. test "defer basics" {
  15. try expect((try deferExample()) == 5);
  16. }

Shell

  1. $ zig test test_defer.zig
  2. 1/1 test_defer.test.defer basics... OK
  3. All 1 tests passed.

Defer expressions are evaluated in reverse order.

defer_unwind.zig

  1. const std = @import("std");
  2. const expect = std.testing.expect;
  3. const print = std.debug.print;
  4. test "defer unwinding" {
  5. print("\n", .{});
  6. defer {
  7. print("1 ", .{});
  8. }
  9. defer {
  10. print("2 ", .{});
  11. }
  12. if (false) {
  13. // defers are not run if they are never executed.
  14. defer {
  15. print("3 ", .{});
  16. }
  17. }
  18. }

Shell

  1. $ zig test defer_unwind.zig
  2. 1/1 defer_unwind.test.defer unwinding...
  3. 2 1 OK
  4. All 1 tests passed.

Inside a defer expression the return statement is not allowed.

test_invalid_defer.zig

  1. fn deferInvalidExample() !void {
  2. defer {
  3. return error.DeferError;
  4. }
  5. return error.DeferError;
  6. }

Shell

  1. $ zig test test_invalid_defer.zig
  2. docgen_tmp/test_invalid_defer.zig:3:9: error: cannot return from defer expression
  3. return error.DeferError;
  4. ^~~~~~~~~~~~~~~~~~~~~~~
  5. docgen_tmp/test_invalid_defer.zig:2:5: note: defer expression here
  6. defer {
  7. ^~~~~

See also: