从零开始学Go之函数(三):宕机与恢复

延迟执行defer:

当某些语句需要函数结束时才使用时,可以使用defer语句

最常用的就是在打开os.Open后加入Close()时用defer避免程序结束未关闭文件

defer 语句

 

例子:
func main() {
 fmt.Println("test")
 for i:=0;i<3 ;i++ {
  fmt.Println(i)
  defer fmt.Println(i)
 }
}

运行结果:

test

0

1

2

2

1

0

 

文件操作例子:
 file, err := os.Open(filename)
 if err != nil {
   return err
 }
 /*
 这里defer要写在err判断的后边而不是os.Open后边
 如果资源没有获取成功,就没有必要对资源执行释放操作
 如果err不为nil而执行资源执行释放操作,有可能导致panic
 */
 defer file.Close()

defer 语句会将函数推迟到外层函数返回之后执行。

推迟调用的函数其参数会立即求值,但直到外层函数返回前该函数都不会被调用。推迟的函数调用会被压入一个栈中(后进先出)。

当外层函数返回时,被推迟的函数会按照后进先出的顺序调用,可能会修改返回值从而得出不正确的结果。

 

宕机panic:

当需要在程序中手动触发宕机时,可以用内置的panic语句

func panic(v interface{})

在panic后剩下的代码都会不会执行,同时会将堆栈和 goroutine 信息输出到控制台

func main() {
 fmt.Println("位置1")
 defer fmt.Println("defer位置1")
 fmt.Println("位置2")
 panic("手动崩溃")
 defer fmt.Println("defer位置2")
 fmt.Println("位置3")
}

 

运行结果

panic: 手动崩溃

位置1

位置2

defer位置1

goroutine 1 [running]:

main.main()

D:/SoloWork/Learn/main.go:13 +0x13a

 

恢复recover:

recover是用来panic时使程序继续运行的函数

func recover() interface{}

使用方法是在panic前先defer声明一个闭包函数,让里面的recover捕捉panic异常,这样当后面遇到不重要的panic时能抛出错误又能让程序继续运行来处理这个错误。

recover之后,逻辑并不会恢复到panic那个点去,函数还是会在defer之后返回,也就是说当前函数会中止,但上层函数会继续运行。

例子:
func main() {
 fmt.Println("位置1")
 defer fmt.Println("defer位置1")
 fmt.Println("位置2")
 defer func() { // 必须要先声明defer,否则不能捕获到panic异常
  fmt.Println("defer进入函数")
  if err := recover(); err != nil {
    fmt.Println(err) // 这里的err其实就是panic传入的内容
  }
  fmt.Println("defer错误处理")
 }()
 panic("崩溃")
 //这里开始向下不会执行
 defer fmt.Println("defer位置2")
 fmt.Println("位置3")
}

运行结果:

位置1

位置2

defer进入函数

崩溃

defer错误处理

defer位置1

func ContinueRun(){
 defer func() { // 必须要先声明defer,否则不能捕获到panic异常
  fmt.Println("defer进入函数")
  if err := recover(); err != nil {
   fmt.Println(err) // 这里的err其实就是panic传入的内容
  }
  fmt.Println("defer错误处理")
 }()
 panic("崩溃")
 fmt.Println("位置4")
}
​
​
func main() {
 fmt.Println("位置1")
 defer fmt.Println("defer位置1")
 fmt.Println("位置2")
 ContinueRun()
 defer fmt.Println("defer位置2")
 fmt.Println("位置3")
}

运行结果:

位置1

位置2

defer进入函数

崩溃

defer错误处理

位置3

defer位置2

defer位置1

posted @ 2019-07-02 00:12  VingB2by  阅读(305)  评论(0编辑  收藏  举报