go--函数调用--defer

知识点1: defer

defer知识点总结

官方文档

https://golang.org/ref/spec#Defer_statements

考点1:defer语句的执行顺序

defer语句的执行顺序如同栈一样,先进后出

  • 例1
// prints 3 2 1 0 before surrounding function returns
for i := 0; i <= 3; i++ {
    defer fmt.Print(i)
}

解答:
defer语句的执行顺序是是先进后出
输出 3 2 1 0

考点1 plus:defer语句与panic语句执行顺序

panic 需要等defer 结束后才会向上传递,所以会先执行defer语句然后执行panic

  • 例2
func defer_call() {
    defer func() { fmt.Println("打印前") }()
    defer func() { fmt.Println("打印中") }()
    defer func() { fmt.Println("打印后") }()

    panic("触发异常")
}

解答:
defer 是后进先出。
panic 需要等defer 结束后才会向上传递。 出现panic恐慌时候,会先按照defer的后入先出的顺序执行,最后才会执行panic。

打印后
打印中
打印前
panic: 触发异常

考点2: defer语句与return语句

注意return语句其实不是一个原子语句,可以拆分成 赋值语句与return 空 语句,赋值语句会在defer之前执行,而return 空语句会在defer执行完之后再执行。

  • 例1
// f returns 42
func f() (result int) {
    defer func() {
        // result is accessed after it was set to 6 by the return statement
        result *= 7
    }()
    return 6
}

解答:
该题目可以改写为

func f() (result int) {
        //赋值语
        result = 6
        defer func() {
            result *= 7
        }()
        //return 空语句
        return
}

这样就很容易看出来了,返回值其实是42而不是6

  • 例2
func f() (result int) {
    defer func() {
        result++
    }()
    return 0
}

解答:
返回值为1

考点3: defer语句与闭包

  • 例1
func f() (r int) {
     t := 5
     defer func() {
       t = t + 5
     }()
     return t
}

解答:
注意f()的入参是r, 而defer函数里的变量为t
拆分return t,可以得到 r=t语句,而且r并没有传入defer func()中,所以return的时候返回的是t的原始值,即5

  • 例2
func f() (r int) {
    defer func(r int) {
          r = r + 5
    }(r)
    return 1
}

解答:
拆分retun 1, 可以得到 r = 1, 然后r作为参数传入了defer func(r int)中, 所以会执行r = r + 5语句,然后再执行return语句。 即最后返回值为 6

考点4: defer保存副本

  • 例1
func hello(i int){
    fmt.Println(i)
}

func main(){
    i := 5
    defer hello(i)
    i = i + 10
}

输出:5
这个例子中,hello()函数的参数在执行defer语句的时候会保存一份副本。在实际调用hello()函数时用,所以是5

你可能感兴趣的:(go--函数调用--defer)