Golang-defer机制
1. 为什么需要defer机制
在项目中,我们常用的操作就是释放资源等操作,为了即时的释放资源,go设计了defer
机制。
2. defer机制的简单实用
我们通过一个案例来看一下defer
机制的作用
import "fmt"
func defer_sum(num1, num2 int) int {
defer fmt.Println("defer1 : ", num1)
defer fmt.Println("defer2 : ", num2)
res := num1 + num2
fmt.Println("sum res : ", res)
return res
}
func main() {
res := defer_sum(10 ,20)
fmt.Println("main : ", res)
}
程序的输出结果如下
sum res : 30
defer2 : 20
defer1 : 10
main : 30
我们可以看到通过defer
声明的操作不会立即执行,而是当所处的代码块执行完成之后才继续执行。
3. defer机制的细节
那么defer机制为什么会产生这样的结果呢,是因为通过defer声明的语句不会立刻执行,而会压入一个defer
栈中,因为栈遵循的是先入后出原则,所以得到如上所示的结果。
在 defer
将语句放入到栈时,也会将相关的值拷贝同时入栈。 我们用一段代码来解释这个特点。这段代码与刚才的那段代码没什么不同,只是在中间加入了一段num1
和num2
自增和自减的操作。
import "fmt"
func defer_sum(num1, num2 int) int {
defer fmt.Println("defer1 : ", num1)
defer fmt.Println("defer2 : ", num2)
num1++
num2--
res := num1 + num2
fmt.Println("sum res : ", res)
return res
}
func main() {
res := defer_sum(10 ,20)
fmt.Println("main : ", res)
}
程序的输出结果如下
sum res : 30
defer2 : 20
defer1 : 10
main : 30
可以看到输出结果与上一个案例的输出结果相同,这也就解释了在**defer
语句入栈的同时也会将值拷贝一份压入栈中。**
4. defer与闭包结合
对闭包不熟悉的可以参看我的这篇博客:Go-闭包
func main() {
for i := 0;i<3 ;i++ {
defer func() {
fmt.Println(i)
}()
}
}
程序的输出结果为
3
3
3
我在Go-闭包这篇博客中讲过,我们可以将闭包中的变量看作是类中的静态变量,再结合defer
机制的性质,得出这样的结果也就不足为奇了。
5. 什么时候使用defer
就像开头提到的,defer机制就是为了更好的关闭资源的,所以我们使用defer
也是在创建资源后使用,如下例所示。
func main(){
connect := connectDB()
defer connect.close()
//对数据库进行其他操作,程序执行完之后会自动进行资源的关闭
}