乐趣区

关于go:关于golang的defer

defer 的执行程序

多个 defer 是一个 的构造,是先进后出,上面这个代码的输入程序是 CBA。

package main

import "fmt"

func main() {defer func1()
    defer func2()
    defer func3()}

func func1() {fmt.Println("A")
}

func func2() {fmt.Println("B")
}

func func3() {fmt.Println("C")
}

defer 和 return 的程序

先执行 return,再执行 defer。

package main

import "fmt"

func deferFunc() {fmt.Println("defer func called")
}

func returnFunc() int {fmt.Println("return func called")
    return 0
}

func returnAndDefer() int {defer deferFunc()
    return returnFunc()}

func main() {returnAndDefer()
}
// output:
// return func called 
// defer func called

函数命名返回值遇见 defer

package main

import "fmt"

func foo() (t int) {defer func() {t = t * 10}()
    return 1
}

func main() {fmt.Println(foo())
}

// output: 10

defer 和 panic

panic 阻断 defer

import ("fmt")

func deferFn() {defer func() {fmt.Println("defer before panic 1") }()
    defer func() { fmt.Println("defer before panic 2") }()

    panic("exit")
    defer func() { fmt.Println("defer after panic") }()}

func main() {deferFn()
    fmt.Println("main exit")
}

/*
output:
defer before panic 2
defer before panic 1
panic: exit
...
*/

defer 外面的 recover

defer 在 panic 后仍然无效

package main

import ("fmt")

func deferFn() {defer func() {fmt.Println("defer before panic 1")
        if err := recover(); err != nil {fmt.Println(err)
        }
    }()

    defer func() { fmt.Println("defer before panic 2") }()
    panic("panic info")
    defer func() { fmt.Println("defer after panic") }()}

func main() {deferFn()
    fmt.Println("main exit")
}
/*
output:
defer before panic 2
defer before panic 1
panic info
main exit
*/

defer 中蕴含 panic

panic 仅有最初一个能够被 revover 捕捉

package main

import ("fmt")

func main() {defer func() {if err := recover(); err != nil {fmt.Println(err)
        } else {fmt.Println("defer call")
        }
    }()

    defer func() {panic("defer panic")
    }()

    panic("main panic")
}

// output: defer panic

defer 中函数有参数和蕴含子函数

package main

import "fmt"

func foo(index int, value int) int {fmt.Println(index)
    return index
}

func main() {defer foo(1, foo(3, 0))
    defer foo(2, foo(4, 0))
}
// output: 3 4 2 1

测试练习

package main

import "fmt"

func DeferFunc1(i int) (t int) {
    t = i
    defer func() {t += 3}()
    return t
}

func DeferFunc2(i int) int {
    t := i
    defer func() {t += 3}()
    return t
}

func DeferFunc3(i int) (t int) {defer func() {t += i}()
    return 2
}

func DeferFunc4() (t int) {defer func(i int) {fmt.Println(i)
        fmt.Println(t)
    }(t)
    t = 1
    return 2
}

func main() {fmt.Println(DeferFunc1(1))
    fmt.Println(DeferFunc2(1))
    fmt.Println(DeferFunc3(1))
    DeferFunc4()}
退出移动版