我可以从紧急状态中恢复,处理错误,然后再次紧急状态并保持原始堆栈跟踪吗?

Is it possible to "rethrow" an error from recover and keep the original stack trace? The best I know how to do is to panic again, but that does create a new stacktrace.

func do() {
    defer func() {
        cleanUp()
        if x := recover(); x != nil {
            handleError()
            panic(x)
        }
    }()
    doStuff()
}

My motivation for wanting this is that unless my function exits normally or handleError runs, my program deadlocks. And unless I preserve the original strack trace, I do not know where it crashed.

The solution is to not call recover, because then neither rethrowing nor accessing the stack trace is possible. Use a bool flag instead of recover to check for panic.

https://play.golang.org/p/PKeP9s-3tF

func do() {
    panicked := true
    defer func() {
        cleanUp()
        if panicked {
            handleError()
        }
    }()
    doStuff()
    panicked = false
}

Defered functions higher up in the stack will run on panic, even if they don't call recover().

Simply remove the if-statement and the re-panic. Then handle your error, and let the panic continue up the stack.

func do() {
    defer handleError()
    doStuff()
}

a simple demo:

https://play.golang.org/p/UiRou5MhUR

func a() {
    defer func() {
        fmt.Println("a")
    }()
    panic("test")
}
func b() {
    defer func() {
        fmt.Println("b")
    }()
}

func main() {
    fmt.Println("Hello, playground")
    b()
}

outputs

Hello, playground
b