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

defer个性:

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

defer用处:

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

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

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

package mainimport "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 mainimport "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 mainimport "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 mainimport "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为形参,它的值受传递的实参来决定的。