Defer and Cleanup
Defer
A defer
always runs at the end of a scope at any point after it is declared, defer
is commonly used to simplify code that needs clean-up; like closing unix file descriptors, freeing dynamically allocated memory or closing database connections.
End of a scope
The end of a scope also includes return
, break
, continue
or !
rethrow.
Rethrow !
unwraps the optional, making it a normal variable again if successful, and if unsuccessful it returns the fault from the function back to the caller.
The defer
runs after the other print statments, at the function return.
Defer Execution order
When there are multiple defer
statements they are executed in reverse order of their declaration, last-to-first decalared.
Example defer
If the file named filename
is found the function will read the content into a buffer, defer
will then make sure that any open File
handlers are closed.
Note that if a scope exit happens before the defer
declaration, the defer
will not run, this a useful property because if the file failed to open, we don’t need to close it.
Defer try
A defer try
is called at end of a scope when exiting with a successful value.
Examples
Function returns a successful value, defer try
runs on scope exit.
Function returns a fault, defer try
does not run on scope exit.
Defer catch
A defer catch
is called at end of a scope when exiting exiting with a fault, and is helpful for cleanup and freeing resources.
When the fault is captured this is convenient for logging the fault:
Memory allocation example
Pitfalls with defer and defer catch
If cleaning up memory allocations or resources make sure the defer
or defer catch
are declared as close to the resource declaration as possible. This helps to avoid unwanted memory leaks or unwanted resource usage from other code rethrowing !
before the defer catch
declaration.