微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决一种不使用最新的err值写长延迟的方法?

我有这个有效的代码

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的值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。