小言_互联网的博客

GO语言教程4:defer(延迟语句)详解

364人阅读  评论(0)


Go语言系列教程:https://blog.csdn.net/zhangpeterx/article/details/89040274


defer是Go语音中非常重要的一个关键字,需要深入的了解。


1.defer语句格式

defer后只能接函数,如:

	defer func() {
		fmt.Println("defer print")
	}()

2.defer执行的时间

defer被称为延迟语句,在return函数执行前执行defer语句。
如:

package main

import "fmt"

func main() {
	defer func() {
		fmt.Println("defer print")
	}()
	fmt.Println("outer print")
}

输出结果如下:

outer print
defer print

3.defer语句的作用

defer语句设计的初衷是用来关闭或释放资源的。
如下:

func main() {
	f, err := os.Create("test.file")
	if err != nil {
		panic("cannot create file")
	}
	defer f.Close()
	// no matter what happens here file will be closed
	// for sake of simplicity I skip checking close result
	fmt.Fprintf(f, "hello")
}

4.defer语句执行的顺序

defer语句执行的顺序是先进后出,也就是栈。
先遇到的defer语句会把函数及其参数压进栈中,最后再统一执行。

func main() {
	for i := 0; i < 4; i++ {
		defer fmt.Println(i)
	}
}

结果如下:

3
2
1
0

如果把代码改为如下:

func main() {
	for i := 0; i < 4; i++ {
		defer func() {
			fmt.Println(i)
		}()
	}
}

输出结果如下:

4
4
4
4

这是因为在运行到defer语句时,i并不是函数参数,是外部变量,所以会直接读取外部变量的值。

5.defer与return的value之间的关系

因为defer语句是延迟执行,那么就涉及到如果defer语句修改了return的value,那么return的结果到底是什么这个问题。
如果函数的返回值是有名变量,那么defer语句可以直接操作变量:

func c() (i int) {
	defer func() { i++ }()
	return 1
}

func main() {
	fmt.Println("c return :", c())
}

输出:

c return : 2

具体过程是:

i=1
i++
return i

如果是无名变量,return最初的结果:

func c() int {
	var i int = 0
	defer func() { i++ }()
	return i
}

func main() {
	fmt.Println("c return :", c())
}

输出:

c return : 0

6.用defer进行代码跟踪

defer语句另一个用法是用来跟踪代码,如在函数开始和结束的时候打印相关信息:

package main

import "fmt"

func trace(s string) string {
	fmt.Println("开始执行", s)
	return s
}
func untrace(s string) {
	fmt.Println("结束执行", s)
}
func a() {
	defer untrace(trace("a"))
	fmt.Println("a的逻辑代码")
}
func b() {
	defer untrace(trace("b"))
	fmt.Println("b的逻辑代码")
	a()
}

func main() {
	b()
}

输出结果如下:

开始执行 b
b的逻辑代码
开始执行 a
a的逻辑代码
结束执行 a
结束执行 b

7.defer一定会被执行吗?

不一定,如果你调用os.Exit(),那么defer不会被执行。


参考:


转载:https://blog.csdn.net/zhangpeterx/article/details/101569212
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场