一、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 中的坑