Go语言关于defer的案例分析

本文围绕Go语言中defer的问题展开分析。通过定义函数F,阐述其调用流程及结果,验证了defer后跟有参数的函数会先计算参数值。还结合不同案例,分析了有返回值函数在加defer后的执行过程,帮助理解defer的机制。

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

遇到一个defer的问题很有意思,咱们来分析一下:

func F(n int) func() int {
	return func() int {
		n++
		return n
	}
}

func main() {
	f := F(5)
	defer func() {
		fmt.Println(f())
	}()
	defer fmt.Println(f())
	i := f()
	fmt.Println(i)
}

首先定义一个函数名称为F参数为int类型返回值为func() int的函数。返回值的参数为空,返回值为int。
调用的时候:
1.调用函数F参数为5,使用接收返回值,因为返回值是个函数,所以这步实际还没有执行F( n int)中return后面的具体内容
2.第一个defer,在函数里面调用了f()
3.第二个defer,直接打印f(),此时f()为函数的参数,所以会先执行f()
4.调用f()将返回值赋值给i
5.打印i
照着这个流程那结果应该是7,6,8
为了更加详细一点,加了几个输出:

func F(n int) func() int {
	return func() int {
		n++
		fmt.Println("里面的:",n)
		return n
	}
}

func main() {
	f := F(5)
	defer func() {
		fmt.Println("第一个:",f())
	}()
	defer fmt.Println("第二个",f())
	i := f()
	fmt.Println(i)
}

输出为:

里面的: 6
里面的: 7
7
第二个 6
里面的: 8
第一个: 8

这也就验证了刚才上面说的过程

总结:
defer后跟的函数,如果有参数的话会先计算参数的值

补充 一下,刚才又遇到另外一个案例,再结合上面的,做一个统一的分析

func main() {

    println(DeferTest1(1))
    println(DeferTest2(1))
}

func DeferTest1(i int) (r int) {
    r = i
    defer func() {
        r += 3
    }()
    return r
}

func DeferTest2(i int) (r int) {
    defer func() {
        r += i
    }()
    return 2
}

之前咱们说过这个案例,现在结合上面的整体的再说一下
go语言有返回值的函数可以理解为这种形式,例如上面的这个return r可以分为两步:先定义一个r变量,初始值为0,然后return即为:
1.r =0
2.return
那如果加了defer呢,这个过程就变为:
1.r=0
2.defer
3.return
这么理解的话上面这个就很简单了,但是这样又有个问题如果返回值没有变量名称呢?
像这样的:

func DeferTest1(i int) int {
	r := i
	defer func() {
		r += 3
	}()
	return r
}

这个返回值是1,结合之前的来看,咱们重新分析一下:
这个过程就相当于:
1.定义一个r变量将i的值传给r
2.对return 后面进行赋值
3.defer
4.return
你这么看的话也就明白为什么会是这种情形了。

咱们再结合上一个案例,其实就可以写成这种:

func F(n int) func() int {
	t := func() int {
		n++
		return n
	}
	return t
}

这样也就能更好的理解这几个案例了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值