根据代码实例运行结果来总结
说明:定义一个函数,有多个defer (用于判断多个defer执行顺序),有panic和 return (判断与defer对比执行顺序)
一、函数中有panic
package main
import "fmt"
func main() {
    fmt.Println("main func start")
    defer func(){
        fmt.Println("main defer func 1")
    }()
    s := test()
    fmt.Println("main get test() return:",s)
}
func test() (str string) {
    defer func() {
        //捕获panic
        if msg := recover(); msg != nil {
            fmt.Println("test defer func1 捕获到错误:",msg)
        }
        str = "bbb"
    }()
    defer func(){
        fmt.Println("test defer func2")
    }()
    defer func(){
        fmt.Println("test defer func3")
    }()
    str = "aaa"
    
    fmt.Println("panic抛出前")
    panic("test painc")
    fmt.Println("panic抛出后")
    
    return str
}
执行结果:
 
   根据执行结果可知道:
- 函数内多个defer执行顺序是 先入后出(即入栈) 
- panic 先于defer执行,不然defer函数内捕获不到错误 
- panic执行后 后续逻辑及return 没有执行 
二、然后将代码中 panic注释掉再执行
 
   执行结果:
 
   根据执行结果可知:
- defer中可以修改返回值,注意:前提是函数的返回值不是匿名的 
三、函数返回的是匿名参数
package main
import "fmt"
func main() {
    fmt.Println("main func start")
    defer func(){
        fmt.Println("main defer func 1")
    }()
    s := test()
    fmt.Println("main get test() return:",s)
}
func test() (string) {
    str := "aaa"
    defer func() {
        //捕获panic
        if msg := recover(); msg != nil {
            fmt.Println("test defer func1 捕获到错误:",msg)
        }
        str = "ccc"
    }()
    defer func(){
        fmt.Println("test defer func2")
    }()
    defer func(){
        fmt.Println("test defer func3")
    }()
    fmt.Println("panic抛出前")
    panic("test painc")
    fmt.Println("panic抛出后")
    return str
}执行结果:
 
   然后注释掉panic执行结果
 
   根据执行结果:
- 函数返回参数是匿名的 defer无法修改 
- 函数中有panic 匿名的返回值是零值,因为return赋值得不到执行,defer又修改不到返回值 
***注意(非常重要):这里需要提到的是函数的return是分为两个步骤:return最先执行,先将结果写入返回值中(即赋值);接着defer开始执行一些收尾工作;最后函数携带当前返回值退出(即返回值)。
有panic的时候,return第一步没有执行到,无法将结果写入返回值中,那么函数退出前则只能返回参数类型的零值
四、总结:
- 函数中有多个defer,则是按先进后出(压栈)执行 
- panic先于defer执行,所以能通过defer中去捕获panic错误 
- defer可以修改函数的返回参数,前提是函数返回的参数不是匿名的 
- 函数执行出现panic那么return得不到执行,如果返回参数是匿名的,那么函数最终返回的是返回参数的类型零值,如果返回参数不是匿名的,在panic前有对返回参数赋值,那么就能返回这个值,如果defer有对其修改,那么返回值则是defer修改的。 


















