小时候经常会听到一个非常浪漫的故事,那就是王子去救公主的故事。
我今天想了想,这好像也可以拿来讲述 Go 语言里面异常错误处理的机制。
这就安排!
刚接触 Golang 的同学,肯定会有一个疑惑就是,咋没有 try catch 这类的错误处理逻辑呀?
没错,Go 里面是没有 try 这类的异常处理机制。
Go 他有他自己的一套错误处理逻辑,那就是 panic 和 recover。
下面大戏开始!
我们先来看三个方法:
func start() {
fmt.Println("王子出发去救公主")
}
func battle() {
fmt.Println("与恶龙大战")
}
func startAgain() {
fmt.Println("再次出发去救公主,并解救成功!")
}
我们就先这样模拟下三个场景吧!
产品:好像少了丰富的故事内涵.... 程序员:你闭嘴!
很久很久以前,阿尔法王国的公主被一条恶龙带走了。
于是国王张榜,招有能王子前去解救王子。
一位身配长剑的王子接下了榜文。
在与国王见面后,就骑上白马前去解救公主了。
城里一位白发老爷爷用 Go 语言,把解救过程用代码写了下来:
func main() {
start()
battle()
comeBack()
}
func start() {
fmt.Println("王子出发去救公主")
}
func battle() {
fmt.Println("与恶龙大战")
}
func comeBack() {
fmt.Println("王子打败了恶龙,解救成功!")
}
并把结果交给了说书人,在大桥下每天重复说着王子的故事:
$ go run main.go
王子出发去救公主
与恶龙大战
王子打败了恶龙,解救成功!
王子和公主在一起没过多久,一个月黑风高伸手不见五指的晚上,公主再次被恶龙捉走了。
于是王子再次请命,出发前去救公主。
白发老爷爷再次用 Go 语言,把解救过程用代码写了下来:
func main() {
start()
battle()
startAgain()
}
func start() {
fmt.Println("王子出发去救公主")
}
func battle() {
fmt.Println("与恶龙大战")
panic("王子受了非常严重的伤....")
}
func startAgain() {
fmt.Println("再次出发去救公主")
}
这次解救失败了!
$ go run main.go
王子出发去救公主
与恶龙大战
panic: 王子受了非常严重的伤....
goroutine 1 [running]:
main.battle(...)
/Users/kun/Desktop/课件/01/main.go:26
main.main()
/Users/kun/Desktop/课件/01/main.go:16 +0xa8
exit status 2
本来王子还想再次出发前去救公主,但是王子受伤太重。
于是国王只能再次张榜,很快一位身配长剑的王子揭榜了。
这个王子,与之前那位不同,在出发之前,要求国王给他配备医疗队跟着。
国王同意了,于是,他出发了。
站在城墙上的白发老爷爷又再次用 Go 语言,把解救过程用代码写了下来:
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("王子被送到救治处: %v \n", err)
fmt.Println("王子被救治成功,满血复活了。")
startAgain()
}
}()
start()
battle()
startAgain()
}
func start() {
fmt.Println("王子出发去救公主")
}
func battle() {
fmt.Println("与恶龙大战")
panic("王子受了非常严重的伤....")
}
func startAgain() {
fmt.Println("再次出发去救公主")
}
过了很久很久,王子终于回来了,马背上还有公主:
$ go run main.go
王子出发去救公主
与恶龙大战
王子被送到救治处: 王子受了非常严重的伤....
王子被救治成功,满血复活了。
再次出发去救公主
于是,王子和公主快乐的在一起了。
当你在写代码时,发现此处有一个致命错误出现,将影响后续的业务,必须在此停止程序。
此时你就可以使用 panic 抛出异常。
在我们的 Go 源码里面,当发生像数组下标越界或类型断言失败这样的运行错误时,Go 运行时会触发运行时 panic。
同时会抛出一个 runtime.Error
接口类型的值。
这个错误值有个 RuntimeError()
方法用于区别普通错误。
用于为处理这个错误提供信息。
而 recover 函数被用于从 panic 或 错误场景中恢复,让程序可以从 panicking 重新获得控制权,停止终止过程进而恢复正常执行。
recover 一般会配合 defer
一起使用,不影响业务代码。