golang的log.Fatal()和panic()函数的区别
在讲两者区别之前我们先看一下os.Exit()函数的定义:
funcExit(codeint) Exitcausesthecurrentprogramtoexitwiththegivenstatuscode. Conventionally,codezeroindicatessuccess,non-zeroanerror. Theprogramterminatesimmediately;deferredfunctionsarenotrun.注意两点:
应用程序马上退出。 defer函数不会执行。再来看log.Fatal函数定义
funcFatal(v...interface{}) FatalisequivalenttoPrint()followedbyacalltoos.Exit(1).看源代码:go/src/log/log.go
//Fatalisequivalenttol.Print()followedbyacalltoos.Exit(1). func(l*Logger)Fatal(v...interface{}){ l.Output(2,fmt.Sprint(v...)) os.Exit(1) }总结起来log.Fatal函数完成:
打印输出内容 退出应用程序 defer函数不会执行和os.Exit()相比多了第一步。
再来看内置函数panic()函数定义:
//Thepanicbuilt-infunctionstopsnormalexecutionofthecurrent //goroutine.WhenafunctionFcallspanic,normalexecutionofFstops //immediately.AnyfunctionswhoseexecutionwasdeferredbyFarerunin //theusualway,andthenFreturnstoitscaller.TothecallerG,the //invocationofFthenbehaveslikeacalltopanic,terminatingGs //executionandrunninganydeferredfunctions.Thiscontinuesuntilall //functionsintheexecutinggoroutinehavestopped,inreverseorder.At //thatpoint,theprogramisterminatedandtheerrorconditionisreported, //includingthevalueoftheargumenttopanic.Thisterminationsequence //iscalledpanickingandcanbecontrolledbythebuilt-infunction //recover. funcpanic(vinterface{})注意几点:
函数立刻停止执行(注意是函数本身,不是应用程序停止) defer函数被执行 返回给调用者(caller) 调用者函数假装也收到了一个panic函数,从而 4.1立即停止执行当前函数 4.2它defer函数被执行 4.3返回给它的调用者(caller) ...(递归重复上述步骤,直到最上层函数) 应用程序停止。 panic的行为简单的总结panic()就有点类似java语言的exception的处理,因而panic的行为和java的exception处理行为就非常类似,行为结合catch,和final语句块的处理流程。
下面给几个例子:
例子1:log.Fatal
packagemain import( "log" ) funcfoo(){ deferfunc(){log.Print("3333")}() log.Fatal("4444") } funcmain(){ log.Print("1111") deferfunc(){log.Print("2222")}() foo() log.Print("9999") }运行结果:
$gobuild&&./main 2018/08/2017:48:441111 2018/08/2017:48:444444可见defer函数的内容并没有被执行,程序在log.Fatal(...)处直接就退出了。
例子2:panic()函数
packagemain import( "log" ) funcfoo(){ deferfunc(){log.Print("3333")}() panic("4444") } funcmain(){ log.Print("1111") deferfunc(){log.Print("2222")}() foo() log.Print("9999") }运行结果:
$gobuild&&./main 2018/08/2017:49:281111 2018/08/2017:49:283333 2018/08/2017:49:282222 panic:4444 goroutine1[running]: main.foo() /home/.../main.go:9+0x55 main.main() /home/.../main.go:15+0x82可见所有的defer都被调用到了,函数根据父子调用关系所有的defer都被调用直到最上层。 当然如果其中某一层函数定义了recover()功能,那么panic会在那一层函数里面被截获,然后由recover()定义如何处理这个panic,是丢弃,还是向上再抛出。(是不是和exception的处理机制一模一样呢?)
原为链接:https://www.jianshu.com/p/f85ecae6e7df
原文链接: