我具有以下代码结构,其中我在同一点的A点锁定了(),并且肯定需要在同一函数中的B点锁定(解锁)。在A点和B点之间,由于需要Unlock()的错误,我有多次返回。使用defer lock.Unlock()A点解决了万一有错误的锁将被释放的问题。但是,如果执行成功到达B点-无论如何我该如何取消该defer和Unlock()?
defer lock.Unlock()
func foo() { ... // point A lock.Lock() defer lock.Unlock() ... err := bar() if err != nil { return } ... //point B - need to definetely unlock here //lock.Unlock() ? }
您无法取消延迟功能。
您可以sync.Once用来确保互斥锁被完全解锁一次:
sync.Once
func foo() { var unlockOnce sync.Once // point A lock.Lock() defer unlockOnce.Do(lock.Unlock) ... err := bar() if err != nil { return } ... // point B - need to unlock here unlockOnce.Do(lock.Unlock) }
如果可能,最好重构代码,以使锁定部分保留在单个函数中:
func fooLock() error { lock.Lock() defer lock.Unlock() if err := bar(); err != nil { return err } ... return nil } func foo() { if err := fooLock(); err != nil { return } ... do the bit that doesn't need a lock }
显然,这里的命名和错误处理很松懈,因为代码是通用的而不是特定的。如果您需要B点之前的代码块中的信息(现在在中的代码中)fooLock,则可以将其与错误一起返回。
fooLock