关于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()
}

你可能感兴趣的:(go)