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

本文详细介绍了Go语言中的defer语句,包括其格式、执行时间、作用、执行顺序、与return的关系以及在代码跟踪中的应用。defer常用于资源关闭和管理,其执行遵循后进先出的原则,且能影响return的值。同时,defer并不总是会被执行,例如在panic情况下。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Go语言系列教程:https://blog.youkuaiyun.com/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不会被执行。


参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值