我正在编写一些事务开始/提交/回滚功能,并且我想配对该块以防止忘记提交
我这样写:
std::enable_if
它可以工作,但是它使用“指向接口的指针”,我找不到有关指向接口的指针的规范。
因此,我不确定此代码是否还可以。你能给些建议吗?
感谢teyzer和Corey Ogburn,这是我的固定解决方案:
func (foo *Foo) Bar() (err error) {
foo.Begin()
defer foo.End(&err)
//some business code
return
}
func (foo *Foo) End(eptr *error) {
// if recover
if r := recover(); r != nil {
debug.PrintStack()
*eptr = r.(error)
}
var err = *eptr
if err != nil {
foo.Rollback()
} else {
foo.Commit()
}
}
答案 0 :(得分:3)
到达defer
时,将立即评估延迟函数的参数。这就是为什么如果推迟End
本身就必须使用指针的原因。
您可以使用闭包。您的Bar()
函数如下所示:
func (foo *Foo) Bar() (err error) {
foo.Begin()
defer func() { foo.End(err) }()
//some business code
return
}
一旦执行了延迟的闭包,就会计算err
的值。
如果您不习惯使用错误返回,那么在Go中使用panic and recovery是更惯用的方式来处理需要回滚的错误(建议使用Corey Ogburn)。
答案 1 :(得分:0)
通常的方法是使用recover()
来捕获任何panic
。您所拥有的与该方法非常相似。 Check out the Go wiki about Panic and Recover
func (foo *Foo) Bar() (err error) {
foo.Begin()
defer foo.End()
//some business code
err = fmt.Errorf("oh no, an error!") // set error so that Bar returns it even though it's caught
panic(err)
return
}
func (foo *Foo) End() {
err := recover()
if err != nil {
foo.Rollback()
} else {
foo.Commit()
}
}