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
mainRunning the program confirms that the file is closed after being written.
$ ruby ensure.rb
creating
writing
closingIn this Ruby version:
We use a
begin/ensureblock in themainmethod to ensure thatclose_fileis called regardless of what happens in thebeginblock.Instead of
panic, we use Ruby’s exception handling withrescueto catch and handle errors.The
createFilefunction is renamed tocreate_fileto follow Ruby naming conventions.We use
File.newinstead ofos.Createto create a new file.In
close_file, we usewarnto print error messages to STDERR.We don’t need to explicitly return the file object in
create_fileas 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.