从GORM里学习到的panic处理方式
今天在博客的评论里,有童鞋提醒我,GORM里也有简化事务处理的帮助函数。源码如下:
// Transaction start a transaction as a block, return error will rollback, otherwise to commit.func (db *DB) Transaction(fc func(tx *DB) error, opts ...*sql.TxOptions) (err error) {panicked := trueif committer, ok := db.Statement.ConnPool.(TxCommitter); ok && committer != nil {// nested transactiondb.SavePoint(fmt.Sprintf("sp%p", fc))defer func() {// Make sure to rollback when panic, Block error or Commit errorif panicked || err != nil {db.RollbackTo(fmt.Sprintf("sp%p", fc))}}()err = fc(db.Session(&Session{WithConditions: true}))} else {tx := db.Begin(opts...)defer func() {// Make sure to rollback when panic, Block error or Commit errorif panicked || err != nil {tx.Rollback()}}()err = fc(tx)if err == nil {err = tx.Commit().Error}}panicked = falsereturn}思路和我的 差不多。
有两个不同,第一,在获取了committer 的时候,会优先选择使用savepoint这个特性,相当于事务里的子事务。
第二,处理panic的方式,这一点值得学习。首先在函数的入口处设置变量:panicked := true,在defer 函数中判断是否panic了,从而进行相应处理:
defer func() {// Make sure to rollback when panic, Block error or Commit errorif panicked || err != nil {db.RollbackTo(fmt.Sprintf("sp%p", fc))}}()那么什么情况下,不会执行呢?当然就是执行到最后的时候,执行了panicked = false 这一行代码之后。
这样就成功避免了使用recover 来判断是否发生了异常。不过也因此,无法在这一层捕捉panic 了。
ref:
邮件 订阅
RSS 订阅
Web开发简介系列
数据结构的实际使用
Golang 简明教程
Python 教程