以下在REPL中有效,如果数据库关闭,我会收回地图。
(try
(insert-table "db" "table" {:id 1 :text "text"})
(catch Exception e {:err "can't connect to database"}))
我虽然可以编写一个带有db操作的函数并用(try)包装它。
(defn catch-db-connection-errors
[db_operation]
(try
(db_operation)
(catch Exception e {:err "can't connect to database"})))
但它没有捕获异常。我可能会忽略一些非常简单的事情......
答案 0 :(得分:3)
问题在于,在调用函数之前会计算作为参数传递的表单(例如(insert-table "db" "table" {:id 1 :text "text"})
),并将结果值传递给函数。要使用其他示例,如果您撰写(println (+ 1 1))
,Clojure将首先评估(+ 1 1)
以获取2
,然后调用(println 2)
。因此,如果在您的数据库代码中抛出异常,则在调用catch-db-connection-errors函数之前,因此在try表单之外。
你想要的是一个宏,谢天谢地是Clojure擅长的东西。
(defmacro catch-db-connection-errors [& db-operations]
`(try
~@db-operations
(catch Exception e {:err "can't connect to database"})))
这允许您传入所需的许多数据库处理表单,并将它们包装在try-catch对中。
(顺便说一句,你可能想要捕捉一些比Exception更具体的东西,否则你最终可能会捕获你不打算做的异常。但当然这不是重点。)