go - 一种不使用最新的err值写长延迟的方法?

标签 go deferred

我有此代码的作品。

func (r *repoPG) WithTransaction(txFunc func() error) (err error) {
    tx := db.NewTx()

    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("panic: %v", r)
            tx.Rollback()
        } else if err != nil {
            tx.Rollback()
        } else {
            tx.Commit()
        }
    }()

    err = txFunc()
    return
}
我想每次都写长长的defer,所以我想写这样的func:
func TxDefer(tx, err) {
  if r := recover(); r != nil {
    err = fmt.Errorf("panic: %v", r)
    tx.Rollback()
  } else if err != nil {
    tx.Rollback()
  } else {
    tx.Commit()
  }
}
像这样使用它:
func (r *repoPG) WithTransaction(txFunc func() error) (err error) {
    tx := db.NewTx()

    defer TxDefer(tx, err)

    err = txFunc()
    return
}
但这是非常不正确的,因为err始终是原始的,而不是txFunc()的结果,对吗?
我怎样才能解决这个问题?

最佳答案

将错误的地址传递给函数。这允许函数访问调用者变量的当前值。它还允许函数设置变量。
回滚和提交返回错误。这些错误应返回给调用方。

func TxDefer(tx Transaction, perr *error) {
  if r := recover(); r != nil {
    *perr = fmt.Errorf("panic: %v", r)
    tx.Rollback()
  } else if *perr != nil {
    err = tx.Rollback()
    if err != nil {
       // replace original error with rollback error
       *perr = err
    }
  } else {
    *perr = tx.Commit()
  }
}
像这样使用它:
func (r *repoPG) WithTransaction(txFunc func() error) (err error) {
    tx := db.NewTx()
    defer TxDefer(tx, &err)
    err = txFunc()
    return
}
在上面的代码中,表达式*perr的计算结果为errWithTransaction的当前值。问题中的err的值是延期时err的值。

关于go - 一种不使用最新的err值写长延迟的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64634177/

相关文章:

mysql - UPDATE SQL 命令不适用于 GO 语言

Go - 如何使用 http.NewRequest 进行测试

javascript - 使用 jQuery.Deferred 代替变量?

javascript - 传递一个向 $.when .done 发出 ajax 请求的函数

javascript - 如何按顺序运行多个函数,并在其中任何一个函数失败时停止所有函数?

javascript - 在继续之前等待函数执行

postgresql - 我如何在 gorm 1.20.0 中关闭数据库实例

用长数字解码的 JSON 给出 float

angularjs + persistencejs + $q (延迟)

postgresql - 运行 postgres 查询时出现无效内存地址错误