在Go语言中,闭包是一种特殊的函数,它引用了其外部作用域中的变量,并且可以在其定义的作用域之外被调用。闭包使得函数可以“记住”并访问它的词法作用域,即使这个函数在词法作用域之外执行。
闭包的基本特性
1.引用外部变量:闭包可以访问并操作定义它的函数作用域中的变量。
2.持久化状态:由于闭包可以记住外部变量,因此可以持久化这些变量的状态。
3.函数作为一等公民:在Go语言中,函数是一等公民,可以像变量一样传递和使用。
go语言函数闭包,就是再不断调用过程中,里面的变量不断改变。就像搭积木一样,每次调用,就会再之前放的积木的基础上再放上一块新积木
package main
import(
"fmt"
)
func A() func(int) int{
var n int = 0
return func( a int) int{
n=a+n
return n
}
}
func main(){
b:=A()
fmt.Println(b(2))
fmt.Println(b(2))
fmt.Println(b(3))
}
在此,我们原来基础上的n就是变量,我们通过两个return的返回,使得形成闭包,A函数最里层的return将n值返还给下面这个函数里。
func A() func(int) int{
var n int = 0
~~~~~~~~~~~
}
}
此时的n值被加载到n的值存放地,n值改变为n=a+n,后面的调动使n不断改变,让我们看看代码结果:
注意事项:
闭包中的变量是引用传递的,因此如果闭包中的变量是可变的(例如指针或切片),那么闭包外部对这些变量的修改会影响到闭包内部。
闭包可能会导致内存泄漏,因为闭包中的变量会一直存在,直到没有引用指向它们为止。所以在使用闭包时需要注意内存管理。
特别注意:
大家看到下面代码,他的输出非常奇怪,文心一言和kimi都给出了错误答案。
package main
import(
"fmt"
)
func A() func(int) int{
var n int = 0
defer fmt.Println("buhao")
fmt.Println("hhhh")
return func( a int) int{
n=a+n
fmt.Println("nihao")
return n
}
}
func main(){
b:=A()
fmt.Println(9)
fmt.Println(b(2))
// fmt.Println(b(2))
// fmt.Println(b(3))
}
都给出的答案是buhao在最下面,但是大家注意,因为A()给予了b,在main里面,一旦被b获取,那么立刻执行A()这个函数,将 defer fmt.Println("buhao"),fmt.Println("hhhh") 这两个语句立马执行。
而为什么被defer的语句也执行?
因为defer在函数里,被推迟发送,但是一旦要进行return之前,便立刻执行defer这个函数,所以我们代码真正的结果是: