199
社区成员
发帖
与我相关
我的任务
分享在go语言中的错误异常,不像其他语言那样try...catch..finally去捕获与控制程序的流程,使用的是多返回值,其中有一个错误的返回,显得特别的简洁,这也是google向来的作风。遇到一些错误的情况,想要恢复如何处理,也就是panic发生错误,然后想使用recover让其恢复。
package main
import "fmt"
func main() {
recover()
panic("发生了错误")
fmt.Println("Hello word!")
}
这种情况发生错误,主程序直接退出,捕获不了错误,recover()放在panic前面和后面都不行。
panic: 发生了错误
goroutine 1 [running]:
main.main()
C:/Users/Tony/test.go:12 +0x31
exit status 2
这个时候要使用defer,顾名思义,推迟,延期的意思,就是出现了错误,延迟处理的意思。
package main
import "fmt"
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
panic("发生了错误")
fmt.Println("Hello word!")
}
C:\Users\Tony>go run test.go
发生了错误
在defer里面捕获错误之后可以正常执行后面的流程:
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
fmt.Println("AAAA")
}()
C:\Users\Tony>go run test.go
发生了错误
AAAA
需要注意的是defer需要在panic前面执行,否则recover不会捕获到这个错误:
package main
import "fmt"
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
fmt.Println("AAAA")
}()
i := make([]int, 2)
fmt.Println(i[3])
}
C:\Users\Tony>go run test.go
runtime error: index out of range [3] with length 2
AAAA
通俗点来说就是panic之后,会走defer这块流程,而不是直接就让程序给崩了。
想深入了解defer和panic可以查看源码:D:\Program Files\Go\src\runtime\runtime2.go,在你的安装目录下面的src目录下面找即可。
type _defer struct {
started bool
heap bool
// openDefer indicates that this _defer is for a frame with open-coded
// defers. We have only one defer record for the entire frame (which may
// currently have 0, 1, or more defers active).
openDefer bool
sp uintptr // sp at time of defer
pc uintptr // pc at time of defer
fn func() // can be nil for open-coded defers
_panic *_panic // panic that is running defer
link *_defer // next defer on G; can point to either heap or stack!
// If openDefer is true, the fields below record values about the stack
// frame and associated function that has the open-coded defer(s). sp
// above will be the sp for the frame, and pc will be address of the
// deferreturn call in the function.
fd unsafe.Pointer // funcdata for the function associated with the frame
varp uintptr // value of varp for the stack frame
// framepc is the current pc associated with the stack frame. Together,
// with sp above (which is the sp associated with the stack frame),
// framepc/sp can be used as pc/sp pair to continue a stack trace via
// gentraceback().
framepc uintptr
}
type _panic struct {
argp unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink
arg any // argument to panic
link *_panic // link to earlier panic
pc uintptr // where to return to in runtime if this panic is bypassed
sp unsafe.Pointer // where to return to in runtime if this panic is bypassed
recovered bool // whether this panic is over
aborted bool // the panic was aborted
goexit bool
}
recover怎么恢复的实现可以查看源码:D:\Program Files\Go\src\runtime\panic.go
当然这些属于底层的东西,有兴趣的可以去熟悉。
欢迎加入我们,一起学习一起进步,有什么疑问尽管问!