go - 一种不使用最新的 err 值编写 long defer 的方法?
问题描述
我有这个有效的代码。
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 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
}
在上面的代码中,表达式计算为in*perr
的当前值。问题中的值是延迟时的值。err
WithTransaction
err
err
推荐阅读
- node.js - Sam 构建失败:构建失败错误:NodejsNpmBuilder:NpmPack - NPM 失败:npm ERR!代码 Z_DATA_ERROR
- php - WithTrashed() 函数删除所有垃圾而不是单个 ID
- css - 表格标题位置粘滞在模板 Web 组件中不起作用?
- cryptography - 最新的 BSAFE 加密库会处理 RSA-8192 密钥和 SHA-512 哈希吗?
- javascript - 如何修复行数不匹配
- serenity-bdd - 在黄瓜+宁静中生成测试报告的问题
- c# - Unauthorized exception when using Azure IoT Hub Device Provisioning Service (DPS)
- python - 从python中的PDF中提取戳记为jpg
- elasticsearch - 如何从 Elasticsearch Kibana 中的索引模式获取在线设备列表
- authentication - 启用其他 KexAlgorihtms