Defer in Clojure
In Clojure, we don’t have a direct equivalent of Go’s defer
keyword. However, we can achieve similar functionality using the try-finally
construct or the with-open
macro for resource management. Let’s see how we can implement the same behavior:
(ns defer-example
(:require [clojure.java.io :as io]))
(defn create-file [path]
(println "creating")
(io/writer path))
(defn write-file [writer]
(println "writing")
(.write writer "data\n"))
(defn close-file [writer]
(println "closing")
(.close writer))
(defn main []
(let [file-path "/tmp/defer.txt"]
(try
(let [writer (create-file file-path)]
(try
(write-file writer)
(finally
(close-file writer))))
(catch Exception e
(println "Error:" (.getMessage e))
(System/exit 1)))))
(main)
In this Clojure version:
We define functions
create-file
,write-file
, andclose-file
that correspond to the Go functions.Instead of using
defer
, we use a nestedtry-finally
block in themain
function. Thefinally
block ensures that the file is closed, similar to howdefer
works in Go.We use
clojure.java.io
for file operations instead of theos
package in Go.Error handling is done using a
try-catch
block, which is more idiomatic in Clojure than Go’s explicit error checking.
To run the program:
$ clj defer_example.clj
creating
writing
closing
This Clojure implementation achieves the same result as the Go version, ensuring that the file is closed after being written, even if an exception occurs during writing.
In Clojure, it’s common to use the with-open
macro for resource management, which automatically closes resources. Here’s an alternative implementation using with-open
:
(ns defer-example
(:require [clojure.java.io :as io]))
(defn write-data [writer]
(println "writing")
(.write writer "data\n"))
(defn main []
(println "creating")
(with-open [writer (io/writer "/tmp/defer.txt")]
(write-data writer))
(println "closing"))
(main)
This version is more concise and automatically handles the closing of the file, similar to how defer
works in Go.
Running this version would produce the same output:
$ clj defer_example.clj
creating
writing
closing
Both implementations demonstrate how to achieve behavior similar to Go’s defer
in Clojure, using either explicit try-finally
blocks or the with-open
macro for resource management.