首页 文章资讯内容详情

golang的log.Fatal()和panic()函数的区别

2026-06-01 4 花语

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

原文链接: