Вы не можете отменить отложенную функцию.
Вы можете использовать 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
}
Очевидно, что именование и обработка ошибок здесь неэффективны, потому что код является обобщенным c и не специфицируется c. Если вам нужна информация из блока кода перед точкой B, которая теперь находится в коде в fooLock
, она может быть возвращена вместе с ошибкой.