文中中所有代码地址:https://github.com/pythonsite/golang_aim

参考文章地址:https://blog.golang.org/defer-panic-and-recover

基础复习

defer

defer 语句经常被用于处理成对的操作,如打开,关闭,连接,端口连接,加锁,释放锁等

延迟语句有是哪个简单的规则:

  • A deferred function’s arguments are evaluated when the defer statement is evaluated.

用于理解的例子:

func a() {
    i := 0
    // 因为i 是值变量,传给fmt.Println的时候传递的是一个拷贝,所以最后打印的是0
    defer fmt.Println(i)
    i++
    return
}
  • Deferred function calls are executed in Last In First Out order after the surrounding function returns.

用于理解的例子:

func b() {
    // defer 函数的执行是后进先出的原则,所以打印的是 3,2,1,0
    for i:=0;i<4;i++ {
        defer fmt.Println(i)
    }
}
  • Deferred functions may read and assign to the returning function’s named return values.

用于理解的例子:

func c() (i int){
    defer func() {i++}()
    return 111
}

前两个例子都比较容易理解,这个规则我个人的理解是: 当前函数的返回值是命名函数,所以延迟函数执行的时候可以读取return 的值 111, 这个之后执行i++ 其实就是对当前函数的return 的值进行+1操作

panic

通常当panic异常发生时,程序会中断运行,并立即执行在该goroutine中被延迟的函数,随后程序崩溃

Recover

通常我们不应该对panic异常做任何处理,但是有的时候我们需要程序从异常中恢复,而recover内置函数可以非常方便地将程序从panic中恢复并返回panic value

defer-panic-recover 例子

package main

import "fmt"

func main() {
    f()
    fmt.Println("Returned normally from f.")
}

func f() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered in f", r)
        }
    }()
    fmt.Println("Calling g.")
    g(0)
    fmt.Println("Returned normally from g.")
}

func g(i int) {
    if i > 3 {
        fmt.Println("Panicking!")
        panic(fmt.Sprintf("%v", i))
    }
    defer fmt.Println("Defer in g", i)
    fmt.Println("Printing in g", i)
    g(i + 1)
}

根据上面的基础知识,这个答案其实对你来说就非常简单了

面试题

面试题来源:golangdeve 公众号

上面基础复习之后再来看一个关于defer的面试题,你就会觉得简单好多

func defer_call() {
    defer func(){
        fmt.Println("打印前")
    }()
    defer func(){
        fmt.Println("打印中")
    }()
    defer func(){
        fmt.Println("打印后")
    }()
    panic("触发异常")
}

相信也也能直接说出答案了