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

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 + 匿名函数 的方式进行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值