Golang recover 函数
最后修改时间 2025 年 5 月 8 日
本教程将介绍如何在 Go 中使用内置的 recover
函数。我们将通过实际的正确错误处理示例来讲解 panic 恢复基础知识。
recover
函数用于重新获得一个正在 panic 的 goroutine 的控制权。它会停止 panic 序列并返回传递给 panic 的值。Recover 仅在 defer 的函数中有用。
在 Go 中,recover
与 panic
和 defer
配合使用,以处理异常情况。它允许在意外错误后进行优雅的关闭或继续执行。
基本的 panic 恢复示例
recover
最简单的用法是捕获 panic 并阻止程序崩溃。此示例演示了基本的 panic 恢复。
注意: Recover 必须在 defer 的函数中调用。
package main import "fmt" func main() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered from panic:", r) } }() panic("something went wrong") fmt.Println("This line won't be executed") }
当发生 panic 时,defer 的函数会调用 recover。在 defer 的函数完成后,程序将继续执行。
从零除恢复
我们可以使用 recover 来处理运行时错误,例如零除。此示例展示了数学运算中的实际错误恢复。
package main import "fmt" func safeDivide(a, b int) (result int, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("division error: %v", r) } }() result = a / b return result, nil } func main() { res, err := safeDivide(10, 0) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Result:", res) } }
safeDivide
函数可以从零除 panic 中恢复。它将 panic 转换为常规的错误返回值。
在 goroutine 中恢复
每个 goroutine 都需要自己的 panic 恢复。此示例展示了如何正确处理并发代码中的 panic。
package main import ( "fmt" "time" ) func worker() { defer func() { if r := recover(); r != nil { fmt.Println("Worker recovered:", r) } }() fmt.Println("Worker started") time.Sleep(1 * time.Second) panic("worker panic") fmt.Println("Worker finished") } func main() { go worker() time.Sleep(2 * time.Second) fmt.Println("Main function completed") }
工作 goroutine 有自己的恢复机制。由于有适当的恢复,panic 不会影响主 goroutine。
使用日志记录进行恢复
我们可以将 recover 与详细的错误日志记录结合起来。此示例演示了带堆栈跟踪的高级 panic 恢复。
package main import ( "fmt" "runtime/debug" ) func riskyOperation() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered from panic:", r) fmt.Println("Stack trace:") debug.PrintStack() } }() var nilMap map[string]string nilMap["key"] = "value" // Will panic } func main() { riskyOperation() fmt.Println("Program continues after recovery") }
恢复处理程序会记录 panic 值和堆栈跟踪。这有助于调试,同时允许程序继续运行。
在 Web 服务器中恢复
Web 服务器应从 panic 中恢复以保持可用性。此示例展示了 HTTP 处理程序中的 panic 恢复。
package main import ( "fmt" "net/http" ) func panicHandler(w http.ResponseWriter, r *http.Request) { defer func() { if r := recover(); r != nil { fmt.Println("Recovered in handler:", r) w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "Internal server error") } }() panic("handler panic") } func main() { http.HandleFunc("/", panicHandler) fmt.Println("Server started on :8080") http.ListenAndServe(":8080", nil) }
HTTP 处理程序可以从 panic 中恢复并返回适当的错误响应。这可以防止整个服务器因单个请求而崩溃。
来源
本教程通过在各种场景下进行 panic 恢复的实际示例,介绍了 Go 中的 recover
函数。