Go 编程 | 连载 26 - Go 的 panic 与 recover
一、panic 和 recover
Go 语言中的错误处理机制是如果一个可能造成错误的函数,需要在该函数的返回值中增加一个错误接口。如果函数调用成功,错误接口将被返回 nil,如果调用失败,则返回具体的错误内容。
在函数调用后需要检查错误,进行必要的错误处理。
在 Go 编程 | 连载 19 - 接口的应用 讲到了实例化错误类型的多种方式,这里不再赘述。
panic
panic 在 Go 语言中表示是宕机,既服务停止或者程序终止运行。
Go 语言中可以手动触发 panic,让程序终止运行,这样可以在程序发生错误时及时止损。panic 发生时会将堆栈和 goroutine 信息输出到控制台,可以据此知晓发生错误的位置,如果在编译时加入的调试信息甚至连 panic 发生时的变量运行状态都可以获得。
func main() {
var info any
info = "crash"
panic(info)
fmt.Println("Hello Go")
}
执行上述代码,输出结果如下:
panic: crash
goroutine 1 [running]:
main.main()
/ex25.go:6 +0x27
只通过一个 panic 函数就是程序终止运行,panic 函数后面的代码也没有执行。panic 函数是 Go 的内置函数,该函数的参数是一个 any 类型,而 any 是一个接口。
当 panic 发生时,panic 函数后的代码将不会被执行,但是 panic 函数前面已经运行过的 defer 语句仍然会在 panic 发生时运行。
func main() {
defer fmt.Println("panic 前")
var info any
info = "crash"
panic(info)
fmt.Println("Hello Go")
defer fmt.Println("panic 后")
}
执行上述代码,输出结果如下:
panic 前
panic: crash
goroutine 1 [running]:
main.main()
/ex25.go:10 +0x73
panic 发生前,在 panic 函数前面的 defer 会优先执行,但是在 panic 函数后的 defer 不会被执行,因为 panic 发生程序停止服务,包括 defer 语句所有的代码都不会被执行。
recover
代码运行时的发生的错误可以通过 defer 和 recover 实现错误捕捉和恢复。让代码发生在泵阔后允许继续运行,类似其他语言中的 try-catch。
Go 中没有异常的概念,只有错误,panic 函数触发宕机就类似于其他语言中的异常。
recover 函数的返回值为任意内容
func recover() any
package main
//noinspection ALL
import (
"fmt"
"runtime"
)
type panicContent struct {
function string
}
//noinspection ALL
func main() {
fmt.Println("手动触发 painc 前")
samFun(func() {
panic(&panicContent{
"手动触发 panic",
})
})
fmt.Println("手动触发 painc 后")
fmt.Println("空指针导致 panic")
samFun(func() {
fmt.Println("赋值前")
var a *int
*a = 1
fmt.Println("赋值后")
})
fmt.Println("panic 后")
}
func samFun(f func()) {
defer func() {
// 发生 panic 时,获取 panic 函数传递的上下文并打印
err := any(recover())
switch err.(type) {
case runtime.Error:
fmt.Println("runtime error:", err)
default:
fmt.Println("error:",err)
}
}()
f()
}
执行上述代码,输出结果如下:
手动触发 painc 前
error: &{手动触发 panic}
手动触发 painc 后
空指针导致 panic
赋值前
runtime error: runtime error: invalid memory address or nil pointer dereference
panic 发生后
panic 函数和 recover 函数同时存在,程序不会宕机,执行对应的 defer 语句后,从宕机点退出当前函数后继续执行。
二、panic 和 recover 的坑

Go 中错误与异常的区分




go 中的 ”try catch“ 这默写

这默写是不行的

panic 中的坑
先写一个 http server


出现异常,服务未停
开启一个协程,在携程中抛出异常
出现异常,服务停止

为什么在主线程中 panic 不会报错导致服务停止,在携程中 panic 就会导致服务停止








在当前携程中捕获异常,防止出现报错


转载自:https://juejin.cn/post/7134267437796573220