对golang中defer的理解

defer是golang中的延迟调用函数,在return之后调用,但实际运用中还是比较难理解的。

理解1:传给defer模块函数的实参会在定义defer时生成备份

如果内部使用的值不是通过形参传递,比如直接引用defer模块外部已经定义好的值,则不会生成备份。
仔细看下面三个函数:

package main
import "fmt"

func c() {
	i := 0
	defer fmt.Println("c1:",i)
	i++
	defer fmt.Println("c2:",i)
}

func cc() {
	i := 0
	defer func() {
	    fmt.Println("cc1:",i)
	}()
	i++
	defer func() {
	    fmt.Println("cc2:",i)
	}()
}

func ccc() {
	i := 0
	defer func(t int) {
	    fmt.Println("ccc1:",t)
	}(i)
	i++
	defer func(t int) {
	    fmt.Println("ccc2:",t)
	}(i)
}
func main() {
	c()
	cc()
	ccc()
}

输出结果为:
c2: 1
c1: 0
cc2: 1
cc1: 1
ccc2: 1
ccc1: 0

函数c()中,c1虽然比c2晚执行,但是c1的结果是小于c2的,这可以看出是c1所在模块定义时,传给该模块的i值是做了备份的。
而函数cc()中,cc1与cc2所在的模块都会在i++之后执行,且模块内的i不是通过形参的方式传入,所以没有生成备份,所以在i++之前或者之后定义这两个defer模块都是一样的效果。
函数ccc()的输出结果与函数c()是一样的,只不过用了一种更容易理解的方式。
函数cc()与函数c()的比较,可以看出,只有传参数给函数才会出现备份效果,直接引用模块外部变量是不会备份的。
通过函数ccc()与函数c()的比较可以看出,各种函数只要通过参数引用的方式传入defer模块,都会生成备份。

理解2:如果在defer内部操作“具名返回值”,是会对返回结果产生影响的

具名返回值,是不是又叫有名返回值???不清楚,我是在B站上学的go语言…
func foo1() int {…}
func foo2() (ret int) {…}
函数foo2()中的返回值已经定义好了,是一个名为ret的int类型的值(具名返回值),如果在defer模块中操作ret,最终函数调用者接收到的返回值不是return时返回的值,而是defer操作后的值。
foo1()中的返回值就是return时返回的值了,不用考虑defer模块中做过什么修改。

看如下代码,先主要看a()与b()两个函数:

package main
import "fmt"

func a() int {
	i := 0 
	defer func() {
	    i++
	    fmt.Println("a:",i)
	}()
	i++
	return i
}

func aa() int {
	i := 0 
	i++
	ret := i
	func() {
	    i++
	    fmt.Println("aa:",i)
	}()
	return ret;
}

func b() (i int) {
	i = 0 
	defer func() {
	    i++
	    fmt.Println("b:",i)
	}()
	i++
	return i
}

func bb() (i int) {
	i = 0 
	i++
	func() {
	    i++
	    fmt.Println("bb:",i)
	}()
	return i
}

func main() {
	fmt.Println("m:",a())
	fmt.Println("m:",b())
}

输出:
a: 2
m: 1
b: 2
m: 2

函数a()的执行顺序实际可以用函数aa()来解释,在函数a()中执行return时,会先定义一个返回变量值ret,然后再去执行defer模块,最后ret会被传回给函数调用者。
如果ret在defer模块中被修改了,函数调用者接收到的值也跟着被修改,就像函数b()中的i已经事先被申明成了返回值,所以执行顺序和bb()是相同的,i的值会在defer中被修改,所以最终函数调用者接收到的值也和a()的不同。

总结

defer的其它特性就不说了,像先定义后执行之类的。
第一次接触defer这个模块时,感觉它和析构函数有点类似。
写得好啰嗦,其它没了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值