golang 中 defer 修改函数返回值的问题

文章探讨了在不同情况下使用defer时,对函数返回值的操作可能导致的结果差异。作者强调了避免直接修改返回值,推荐使用defer配合匿名函数来处理返回值相关操作的重要性。

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

0x00 写在前面

笔者在使用 defer 时发现如果涉及到更改函数返回值之情况,不同的代码写法存在不同的结果,暂列出如下几种情况。

0x01 几种情况

以下方法的返回值都通过调用方打印,并且返回值的打印都晚于方法内部 defer 的打印

type deferSt struct {
	num int
}

// 直接传值调用函数的方式
func DeferNormal() int {
	var i int = 1
	defer fmt.Println(i)
	i++
	return i
}
--------------------
1
2
--------------------


// 指针调用函数的方式
func DeferPoint() int {
	s := make([]int, 2)
	defer fmt.Println(s)
	s[0] = 2
	return s[0]
}
--------------------
[2 0]
2
--------------------


// 匿名函数的方式捕获内部变量
func DeferNormalFunc() int {
	var i int = 1
	defer func() {
		fmt.Println(i)
	}()
	i++
	return i
}
--------------------
2
2
--------------------


// 匿名函数捕获指针变量的方式
func DeferPointFunc() int {
	st := &deferSt{}
	defer func() {
		fmt.Println(st)
	}()
	st.num = 1
	return st.num
}
--------------------
&{1}
1
--------------------


// 匿名函数修改具名返回值的值
func DeferClearName() (ret int) {
	ret = 1
	defer func() {
		ret++
		fmt.Println(ret)
	}()
	return ret
}
--------------------
2
2
--------------------


// 匿名函数修改匿名返回值的值
func DeferUnclearName() int {
	var i int = 1
	defer func() {
		i++
		fmt.Println(i)
	}()
	return i
}
--------------------
2
1
-------------------- 


// 匿名函数捕获指针变量的方式(引用类型)
func DeferUnclearPoint() int {
	st := &deferSt{}
	defer func() {
        st.num = 1
		fmt.Println(st)
	}()
	return st.num
}
--------------------
&{1}
0
-------------------- 

从上述几种情况中可以看出,除直接传值调用方法及修改匿名返回值之外,其余返回值都与 defer 中的值一致。

0x02 写在后边

综上,尽量不要在 defer 中修改返回值,如果要使用返回值进行某些操作尽量使用 defer + 匿名函数 的方式进行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值