关于golang:golang-defer详细讲解

32次阅读

共计 1786 个字符,预计需要花费 5 分钟才能阅读完成。

Golang 开发文档 https://www.topgoer.com/%E5%8…

defer 个性:

  1. 关键字 defer 用于注册提早调用。
  2. 这些调用直到 return 前才被执。因而,能够用来做资源清理。
  3. 多个 defer 语句,按先进后出的形式执行。
  4. defer 语句中的变量,在 defer 申明时就决定了。

defer 用处:

  1. 敞开文件句柄
  2. 锁资源开释
  3. 数据库连贯开释

依据开发文档形容,上面来做一一验证。

1.defer 用于注册提早调用。

package main

import "fmt"

func main()  {fmt.Println("测试 defer start")
    defer func() {fmt.Println("defer func")
    }()
    fmt.Println("测试 defer end")
}

执行后果为:

证实 defer 函数用来提早调用,在函数完结的时候被调用。函数完结包含:被调用办法失常 return,或者达到办法体结尾,也或者蕴含 defer 函数的办法在执行 panic 的时候都会执行 defer 函数。

值得注意是,当蕴含 defer 函数的办法在执行 panic 操作的时候,会先执行 defer 函数,再执行 panic 办法,panic 之后的语句是不可达的。上面我用实例来再次证实一下。

package main

import "fmt"

func main()  {fmt.Println("测试 defer start")
    defer func() {fmt.Println("defer func")
    }()
    fmt.Println("测试 defer end")
    panic("panic 异样")
}

执行后果为:

由此看出,defer 产生在 panic 执行之前,因而,能够在 defer 办法外面做资源清理,开释操作。

2. 多个 defer 语句,按先进后出的形式执行。

package main

import "fmt"

func main()  {deferFunc1()
}

func deferFunc1()  {

    val := "1111"
    defer fmt.Println("val1",val)
    defer func() {fmt.Println("val2",val)
    }()
    defer fmt.Println("val3",val)

    defer func(val string) {fmt.Println("val4",val)
    }(val)
    defer fmt.Println("val5",val)

    fmt.Println("val",val)
}

执行后果为:

简略了解就是:定义 defer 相似于入栈操作,执行 defer 相似于出栈操作,先进后出。

3.defer 语句中的变量,在 defer 申明时就决定了。

package main

import "fmt"

func main()  {deferFunc1()
}

func deferFunc1()  {

    val := "1111"
    defer fmt.Println("val1",val)
    defer func() {fmt.Println("val2",val)
    }()
    defer fmt.Println("val3",val)

    val = "2222"
    defer func(val string) {fmt.Println("val4",val)
    }(val)
    defer fmt.Println("val5",val)

    val = "3333"
    defer func() {fmt.Println("val6",val)
    }()
    fmt.Println("val",val)
}

此时,能够考虑一下下面程序输入后果是啥?为什么?针对下面程序有几个易错点,常常被作为面试的口试题来考查求职者对 defer 的了解。

上面看一张很经典的图片,golang 程序调用程序图。

var 这些变量是依照由上到下赋值的,联合下面程序来说,val 变量最初被赋值为 ”3333″,而 defer 又是推延函数,按理说所有 defer 蕴含的提早函数的 val 都是 ”3333″ 才对,然而执行后果出乎咱们的预料。

由下面后果能够看出:
defer 间接执行 fmt.Println 函数,val 变量的值对应的由上到下最近赋值变量的值。
defer 执行 func(){}() 时,val 变量的值对应最初赋值的值。这里还有一种非凡状况,defer func(val string) {}(val) 将变量传递到 defer 函数外面,此时 func(val string) val 为形参,它的值受传递的实参来决定的。

正文完
 0