Defer in Ruby
Here’s the Ruby translation of the Go “Defer” example, formatted in Markdown for Hugo:
Our example demonstrates the use of ensure
in Ruby, which is similar to defer
in other languages. It’s used to ensure that a piece of code is executed, usually for cleanup purposes, regardless of whether an exception is raised or not.
require 'fileutils'
def main
# Immediately after getting a file object with
# create_file, we use a begin/ensure block to ensure
# the file is closed after we're done writing to it.
begin
f = create_file("/tmp/ensure.txt")
write_file(f)
ensure
close_file(f)
end
end
def create_file(path)
puts "creating"
File.new(path, "w")
rescue StandardError => e
puts "Error: #{e.message}"
exit(1)
end
def write_file(file)
puts "writing"
file.puts "data"
end
# It's important to check for errors when closing a
# file, even in an ensure block.
def close_file(file)
puts "closing"
file.close
rescue StandardError => e
warn "Error: #{e.message}"
exit(1)
end
main
Running the program confirms that the file is closed after being written.
$ ruby ensure.rb
creating
writing
closing
In this Ruby version:
We use a
begin/ensure
block in themain
method to ensure thatclose_file
is called regardless of what happens in thebegin
block.Instead of
panic
, we use Ruby’s exception handling withrescue
to catch and handle errors.The
createFile
function is renamed tocreate_file
to follow Ruby naming conventions.We use
File.new
instead ofos.Create
to create a new file.In
close_file
, we usewarn
to print error messages to STDERR.We don’t need to explicitly return the file object in
create_file
as Ruby automatically returns the last evaluated expression.
This example demonstrates how Ruby’s ensure
can be used to handle cleanup operations, similar to defer
in other languages.