遇到一个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
}
这样也就能更好的理解这几个案例了。