database / sql Tx – 检测提交或回滚

前端之家收集整理的这篇文章主要介绍了database / sql Tx – 检测提交或回滚前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
使用数据库/ sql和驱动程序包和Tx,似乎无法检测事务是否已提交或回滚,而不尝试另一个事件并因此而收到错误,然后检查错误以确定错误.我想能够从Tx对象确定是否进行.当然,我可以在使用Tx的函数中定义和设置另一个变量,但是我有相当多的它们,每次都是次数(变量和赋值).如果需要,我还有一个延迟函数来执行Rollback,并且需要传递bool变量.
在提交或回滚之后将Tx变量设置为n可以接受,并且GC将恢复任何内存,或者是否否,还是有更好的选择?

解决方法

为什么你甚至需要这样做?调用Begin()的函数也应该调用Commit()或Rollback()并返回一个适当的错误.

例如,此代码根据是否返回错误执行提交或回滚:

func (s Service) DoSomething() (err error) {
    tx,err := s.db.Begin()
    if err != nil {
        return
    }
    defer func() {
        if err != nil {
            tx.Rollback()
            return
        }
        err = tx.Commit()
    }()
    if _,err = tx.Exec(...); err != nil {
        return
    }
    if _,err = tx.Exec(...); err != nil {
        return
    }
    // ...
    return
}

请注意我如何检查错误,看我是否应该提交或回滚.然而,上述示例并不处理恐慌.

我不喜欢在每个数据库例程上执行提交/回滚逻辑,所以我通常将它们包装在一个事务处理程序中.一些这样的事情:

func Transact(db *sql.DB,txFunc func(*sql.Tx) error) (err error) {
    tx,err := db.Begin()
    if err != nil {
        return
    }
    defer func() {
        if p := recover(); p != nil {
            switch p := p.(type) {
            case error:
                err = p
            default:
                err = fmt.Errorf("%s",p)
            }
        }
        if err != nil {
            tx.Rollback()
            return
        }
        err = tx.Commit()
    }()
    err = txFunc(tx)
    return err
}

这样我就可以做到这一点:

func (s Service) DoSomething() error {
    return Transact(s.db,func (tx *sql.Tx) error {
        if _,err := tx.Exec(...); err != nil {
            return err
        }
        if _,err := tx.Exec(...); err != nil {
            return err
        }
    })
}

请注意,如果我的事务中的任何事情都是混乱,它将被事务处理程序自动处理.

在我的实际实现中,我传递一个接口而不是* sql.Tx,以防止对Commit()或Rollback()的不必要的调用.

这是一个简单的代码段,用于演示延迟工作方式(打印4,而不是5):

package main

func test() (i int) {
    defer func() {
        i = 4
    }()
    return 5
}

func main() {
    println(test())
}

http://play.golang.org/p/0OinYDWFlx

猜你在找的MsSQL相关文章