简介
闭包是由函数和与其相关的引用环境组合而成的实体
闭包的简单使用
func add() func() int {
var sum int
return func() int {
sum++
return sum
}
}
调用add
函数回返回一个返回值为int
类型的函数
x:=add()
fmt.Println(x())
fmt.Println(x())
fmt.Println(x())
x
保存了sum
的引用,x
成为了一个闭包
运行结果
println(add()())
println(add()())
println(add()())
上述情况调用三次函数,返回了三个闭包,分别各自引用不同的变量
运行结果
闭包引用
sum := 1
a := func() {
println(sum)
}
sum = 2
sum = 3
a()
运行结果
很好理解,因为闭包保存了sum
的引用
sum := 1
a := func() {
fmt.Println(sum)
}
a()
sum = 2
sum = 3
运行结果
很简单,因为调用a
时已经解引用,之后的修改与它再无关系
循环闭包引用
情景一
for i := 0; i < 3; i++ {
func() {
fmt.Println(i)
}()
}
运行结果
情景二
var a func()
for i := 0; i < 3; i++ {
a = func() {
fmt.Println(i)
}
}
a()
运行结果
原因是循环直到i
为3的时候才结束,与之不同的是range
var array [3]int
var a func()
for i := range array {
a = func() {
fmt.Println(i)
}
}
a()
运行结果
情景三
var Closures []func()
for i := 0; i < 5; i++ {
Closures = append(Closures, func() {
fmt.Println(i)
})
}
for j := 0; j < 5; j++ {
Closures[j]()
}
运行结果
解决
方法一,函数传参
var Closures []func()
for i := 0; i < 5; i++ {
func(i int) {
Closures= append(Closures, func() {
fmt.Println(i)
})
}(i)
}
for j := 0; j < 5; j++ {
Closures[j]()
}
方法二,声明新变量
var Closures []func()
for i := 0; i < 5; i++ {
z:=i
Closures = append(Closures, func() {
println(z)
})
}
for j := 0; j < 5; j++ {
Closures[j]()
}
运行结果均为