29_errdefer.zig 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. //
  2. // Another common problem is a block of code that could exit in multiple
  3. // places due to an error - but that needs to run do something before it
  4. // exits (typically to clean up after itself).
  5. //
  6. // An "errdefer" is a defer that only runs if the block exits with an error:
  7. //
  8. // {
  9. // errdefer cleanup();
  10. // try canFail();
  11. // }
  12. //
  13. // The cleanup() function is called ONLY if the "try" statement returns an
  14. // error produced by canFail().
  15. //
  16. const std = @import("std");
  17. //
  18. var counter: u32 = 0;
  19. const MyErr = error{ GetFail, IncFail };
  20. pub fn main() void {
  21. // We simply quit the entire program if we fail to get a number:
  22. var a: u32 = makeNumber() catch return;
  23. var b: u32 = makeNumber() catch return;
  24. std.debug.print("Numbers: {}, {}\n", .{a,b});
  25. }
  26. fn makeNumber() MyErr!u32 {
  27. std.debug.print("Getting number...", .{});
  28. // Please make the "failed" message print ONLY if the makeNumber()
  29. // function exits with an error:
  30. std.debug.print("failed!\n", .{});
  31. var num = try getNumber(); // <-- This could fail!
  32. num = try increaseNumber(num); // <-- This could ALSO fail!
  33. std.debug.print("got {}. ", .{num});
  34. return num;
  35. }
  36. fn getNumber() MyErr!u32 {
  37. // I _could_ fail...but I don't!
  38. return 4;
  39. }
  40. fn increaseNumber(n: u32) MyErr!u32 {
  41. // I fail after the first time you run me!
  42. if (counter > 0) return MyErr.IncFail;
  43. // Sneaky, weird global stuff.
  44. counter += 1;
  45. return n + 1;
  46. }