panic使用
# Go panic
介绍
在 Go 语言中,panic
是用于引发程序运行时错误的内置函数。调用 panic
会导致程序立即停止正常执行,并进入恐慌状态,执行调用栈中的**延迟函数(defer)**后退出程序。
panic
通常用于以下场景:
- 不可恢复的错误:程序无法继续运行,必须立即停止。
- 编程错误:例如数组越界、无效类型断言等。
# 1. panic
的语法
panic("error message")
1
当 panic
被调用时:
- 当前函数停止执行。
- 延迟(
defer
)语句会按照调用顺序的逆序执行。 - 程序崩溃并打印错误信息,包括调用栈。
# 2. 使用案例
# 2.1 简单的 panic
示例
package main
import "fmt"
func main() {
fmt.Println("Start")
panic("Something went wrong!")
fmt.Println("End") // 不会执行
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
输出:
Start
panic: Something went wrong!
goroutine 1 [running]:
main.main()
/path/to/code.go:6 +0x49
exit status 2
1
2
3
4
5
6
7
2
3
4
5
6
7
- 解释:调用
panic
后,fmt.Println("End")
不会执行。
# 2.2 延迟函数与 panic
defer
语句在 panic
发生时仍然会被执行,可以用于释放资源、打印日志等操作。
package main
import "fmt"
func main() {
defer fmt.Println("Defer 1 executed")
defer fmt.Println("Defer 2 executed")
fmt.Println("Before panic")
panic("Something went wrong!")
fmt.Println("After panic") // 不会执行
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
输出:
Before panic
Defer 2 executed
Defer 1 executed
panic: Something went wrong!
goroutine 1 [running]:
main.main()
/path/to/code.go:9 +0x49
exit status 2
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
- 解释:
defer
的调用顺序是后进先出。
# 3. 捕获 panic
(recover
)
Go 提供了内置函数 recover
,用于捕获并处理 panic
,避免程序崩溃。
# 3.1 recover
的基本用法
recover
只能在延迟函数中调用。如果在延迟函数中捕获到 panic
,程序将恢复正常执行。
package main
import "fmt"
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
fmt.Println("Before panic")
panic("Something went wrong!")
fmt.Println("After panic") // 不会执行
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
输出:
Before panic
Recovered from panic: Something went wrong!
1
2
2
# 3.2 使用 recover
的实际场景
保证服务稳定性:在服务端程序中,
panic
可能会因为意外导致服务崩溃。可以使用recover
捕获异常,防止整个服务退出。资源清理:在
panic
发生时,使用recover
捕获错误并完成资源清理。
# 示例:Web 服务器中使用 recover
package main
import (
"fmt"
"net/http"
)
func recoverMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
fmt.Println("Recovered from panic:", err)
}
}()
next(w, r)
}
}
func handler(w http.ResponseWriter, r *http.Request) {
panic("unexpected error!")
}
func main() {
http.HandleFunc("/", recoverMiddleware(handler))
fmt.Println("Server is running on port 8080")
http.ListenAndServe(":8080", nil)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- 解释:
- 当
handler
中发生panic
时,recoverMiddleware
会捕获错误并返回 HTTP 500 响应,而不会导致服务器崩溃。
- 当
# 4. panic
和 recover
的实际应用
# 4.1 自定义错误处理函数
package main
import (
"fmt"
)
func safeExecute(fn func()) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
fn()
}
func riskyOperation() {
panic("critical failure")
}
func main() {
fmt.Println("Starting program")
safeExecute(riskyOperation)
fmt.Println("Program continues after recovery")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
输出:
Starting program
Recovered from panic: critical failure
Program continues after recovery
1
2
3
2
3
# 4.2 数据库连接中的 panic
处理
package main
import (
"database/sql"
"fmt"
_ "github.com/mattn/go-sqlite3"
)
func connectDatabase() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic during database connection:", r)
}
}()
panic("Unable to connect to database")
}
func main() {
connectDatabase()
fmt.Println("Program continues after recovery")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
输出:
Recovered from panic during database connection: Unable to connect to database
Program continues after recovery
1
2
2
# 5. panic
与错误处理的区别
特点 | panic | 错误处理 (error ) |
---|---|---|
使用场景 | 不可恢复的致命错误,如编程逻辑错误。 | 可恢复的错误,例如文件未找到、网络错误 |
是否终止程序 | 是(除非使用 recover 捕获)。 | 否,需显式处理。 |
适合场景 | 仅用于严重错误,或者库内部无法处理的问题。 | 常见错误处理,推荐的方式。 |
灵活性 | 简单粗暴,直接终止当前函数。 | 更灵活,可逐步返回错误到调用方。 |
# 6. 总结
panic
是 Go 中处理不可恢复错误的工具,应谨慎使用。defer
与recover
搭配可以捕获panic
,从而避免程序崩溃。- 实际开发中,
panic
常用于:- 处理编程中的致命错误。
- 防止库的错误传播到外部。
- Go 推荐使用
error
返回值处理常规错误,而非依赖panic
。
上次更新: 2024/11/21, 10:50:23