小白学go-day04 递归函数和闭包函数

递归函数

简单来讲就是自己调用自己,达到临界值,就不调用了。

我们先来看一个简单的递归。

典型的例子:斐波那契数列

什么是斐波那契数列?

从第三项开始,每一项都等于前两项之和

1,1,2,3,5,8,13…这样的数列就是斐波那契数列
1+1=2
1+2=3
2+3=5

在这里插入图片描述

也就是这样写就是一个递归函数

定义一个fb的函数返回值是调用自己 当n=0时停止递归。

闭包

现在开始通过例子来说明闭包:

func incr() func() int {
	var x int
	return func() int {
		x++
		return x
	}
}

调用这个函数会返回一个函数变量。

i := incr():通过把这个函数变量赋值给 ii 就成为了一个闭包

所以 i 保存着对 x 的引用,可以想象 i 中有着一个指针指向 xi 中有 x 的地址

由于 i 有着指向 x 的指针,所以可以修改 x,且保持着状态:

println(i()) // 1
println(i()) // 2
println(i()) // 3

也就是说,x 逃逸了,它的生命周期没有随着它的作用域结束而结束。

但是这段代码却不会递增:

println(incr()()) // 1
println(incr()()) // 1
println(incr()()) // 1

这是因为这里调用了三次 incr(),返回了三个闭包,这三个闭包引用着三个不同的 x,它们的状态是各自独立的。

闭包引用

现在开始通过例子来说明由闭包引用产生的问题:

x := 1
f := func() {
	println(x)
}
x = 2
x = 3
f() // 3

因为闭包对外层词法域变量是引用的,所以这段代码会输出 3

可以想象 f 中保存着 x 的地址,它使用 x 时会直接解引用,所以 x 的值改变了会导致 f 解引用得到的值也会改变。

但是,这段代码却会输出 1

x := 1
func() {
	println(x) // 1
}()
x = 2
x = 3

把它转换成这样的形式就容易理解了:

复制代码
x := 1
f := func() {
	println(x)
}
f() // 1
x = 2
x = 3

这是因为 f 调用时就已经解引用取值了,这之后的修改就与它无关了。

不过如果再次调用 f 还是会输出 3,这也再一次证明了 f 中保存着 x 的地址。

可以通过在闭包内外打印所引用变量的地址来证明:

x := 1
func() {
	println(&x) // 0xc0000de790
}()
println(&x) // 0xc0000de790

可以看到引用的是同一个地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值