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将语句放入到栈时,也会将相关的值拷贝同时入栈。 我们用一段代码来解释这个特点。这段代码与刚才的那段代码没什么不同,只是在中间加入了一段num1num2自增和自减的操作。

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()
    //对数据库进行其他操作,程序执行完之后会自动进行资源的关闭
}
发布了31 篇原创文章 · 获赞 25 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/s_842499467/article/details/104283109