我已开始在 web 服务中使用 Go,并且有一些数据库交互(惊喜!!!)我发现了这个例子:
tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}
defer tx.Rollback()
stmt, err := tx.Prepare("INSERT INTO foo VALUES (?)")
if err != nil {
log.Fatal(err)
}
defer stmt.Close() // danger!
for i := 0; i < 10; i++ {
_, err = stmt.Exec(i)
if err != nil {
log.Fatal(err)
}
}
err = tx.Commit()
if err != nil {
log.Fatal(err)
}
// stmt.Close() runs here!
来自http://go-database-sql.org/prepared.html
这个例子写得很好,易于理解。然而,它让我有一个未解答的问题。为什么要defer
事务Rollback调用?
为什么不直接这样做:
err := tx.Commit()
if err != nil {
log.Error(err)
tx.Rollback()
}
< p>如果tx.Commit()
成功,那么defer tx.Rollback()
不会尝试回滚吗?或者我对defer
的理解有误?
defer tx.Rollback()
可以很好地避免在事务生命周期中的每个错误都放置回滚逻辑。请注意,如果事务已经提交,则调用回滚将执行“NOP”。话虽如此,随着冗余性的增加,控制力也会增加,因此如果速度是一个问题,则处理每个回滚而不是使用defer
可能更可取(或用于详细记录日志等)。 - Kelly Flet