Defer in Crystal
# Defer is used to ensure that a function call is performed later in a program's
# execution, usually for purposes of cleanup. In Crystal, we use `ensure` blocks
# for similar purposes.
require "file"
# Suppose we wanted to create a file, write to it,
# and then close when we're done. Here's how we could
# do that with `ensure`.
def main
# Immediately after getting a file object with
# `File.new`, we put the closing of that file
# in an `ensure` block. This will be executed at the end
# of the enclosing function (`main`), after
# `write_file` has finished.
f = create_file("/tmp/defer.txt")
begin
write_file(f)
ensure
close_file(f)
end
end
def create_file(p : String) : File
puts "creating"
File.new(p, "w")
rescue ex
puts "Error: #{ex.message}"
exit(1)
end
def write_file(f : File)
puts "writing"
f.puts "data"
end
# It's important to check for errors when closing a
# file, even in an ensure block.
def close_file(f : File)
puts "closing"
f.close
rescue ex
STDERR.puts "error: #{ex.message}"
exit(1)
end
mainRunning the program confirms that the file is closed after being written.
$ crystal run defer.cr
creating
writing
closingIn Crystal, we use ensure blocks to achieve similar functionality to Go’s defer. The ensure block guarantees that the code within it will be executed when the enclosing method exits, regardless of whether an exception was raised or not.
The structure of the program remains similar, but we’ve made a few Crystal-specific adjustments:
- We use
require "file"instead of importing specific packages. - We define a
mainmethod and call it at the end of the file, as Crystal doesn’t have a specialmainfunction. - Instead of using
defer, we use abegin/ensureblock to ensure the file is closed. - We use Crystal’s exception handling (
rescue) instead of explicitly checking for errors. - We specify types for method parameters and return values.
- We use
File.newinstead ofos.Createto create a file. - We use
STDERR.putsinstead offmt.Fprintf(os.Stderr, ...)for error output.
This Crystal code provides the same functionality as the original Go code, ensuring that resources are properly cleaned up using ensure blocks.
Comments powered by Disqus