多个延迟执行语句的处理顺序函数
package main import ( "fmt" ) func main() { fmt.Println("defer begin") // 将defer放入延迟调用栈 defer fmt.Println(1) defer fmt.Println(2) // 最后一个放入, 位于栈顶, 最早调用 defer fmt.Println(3) fmt.Println("defer end") }
结果分析以下:spa
处理业务或逻辑中涉及成对的操做是一件比较烦琐的事情,好比打开和关闭文件、接收请求和回复请求、加锁和解锁等。在这些操做中,最容易忽略的就是在每一个函数退出处正确地释放和关闭资源。
defer 语句正好是在函数退出时执行的语句,因此使用 defer 能很是方便地处理资源释放问题。code
package main func main() { panic("crash") }
当 panic() 触发的宕机发生时,panic() 后面的代码将不会被运行,可是在 panic() 函数前面已经运行过的 defer 语句依然会在宕机发生时发生做用,参考下面代码blog
package main import "fmt" func main() { defer fmt.Println("宕机后要作的事情1") defer fmt.Println("宕机后要作的事情2") panic("宕机") }
输出结果为:资源
宕机后要作的事情2 宕机后要作的事情1 panic: 宕机 goroutine 1 [running]: main.main() F:/src/tester/main.go:8 +0x1a4
不管是代码运行错误由 Runtime 层抛出的 panic 崩溃,仍是主动触发的 panic 崩溃,均可以配合 defer 和 recover 实现错误捕捉和恢复,让代码在发生崩溃后容许继续运行。class
defer func() { if r:= recover();r != nil{ log.Printf("Runtime error caught :%v",r) } }() foo()