闭包:
闭包指的是在一个函数内部定义另外一个函数,并且返回该函数的情况,在这种情况下,内部函数可以访问外部函数的变量和参数,并且在外部函数调用之后仍然可以使用他们
通俗易懂的说,闭包就像是一个函数内部的小盒子,,里面可以保存外部函数的变量和参数,当外部函数结束时,这个·小盒子仍然可以被其他的代码所引用,并且其中的变量和参数也保留了下来,不会被销毁。
举个例子,假设有一个函数a,其中包含一个变量x,还定义了一个函数b,并返回b。那么当你调用a()时,a函数执行完毕退出,但由于函数b存储了a中的变量x,所以x并没有销毁,而是被封装在了函数b中。因此,当你通过b()调用函数b时,它还可以访问和修改x。
优点:
这种机制对于编写高效、灵活且可重用的代码非常有用。例如,您可以将外部变量传递给返回的内部函数,并在多次调用之间保存状态。同时,您也可以隐藏不需要暴露在函数外部的信息,增强了函数的安全性和隐私性。
例子:
package main
import "fmt"
// 返回一个函数
func add() func(int) int {
var x int
return func(y int) int {
x += y
return x
}
}
func main() {
var f = add()
fmt.Println(f(10))/*这行代码 调用了 返回给变量 的匿名函数,并给该匿名函数的参数值传递了整数 。fmt.println(f(10))add()f10
由于 函数使用闭包来创建并返回匿名函数,所以调用 时,首先会将 设置为 ,然后将其添加到 中。由于 是在外部函数中声明的变量并在内部函数中引用,所以在每次调用 时,都会更新 的值。add()f(10)y10xxf()x
因此,第一次调用 后, 的值变为 ,将其返回给 打印,并输出结果 。
而后续第二个和第三个调用分别将 设置为 和 ,分别加到 上,最终的输出结果依次是 和 。f(10)x10fmt.println()10y2030x3060
请注意,第一个 后面没有换行符标志,因此下一个输出语句输出的结果与前一个语句的结果打印在同一行上。 "-----------" 可被视为输出所属列表的分隔符。fmt.println()10, 20, 30*/
fmt.Println(f(20))
fmt.Println(f(30))
fmt.Println("-----------")
f1 := add()
fmt.Println(f1(40))
fmt.Println(f1(50))
}
运行结果
10
30
60
-----------
40
90
例子2:
func makeSuffixFunc(suffix string) func(string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}
func main() {
jpgFunc := makeSuffixFunc(".jpg")
txtFunc := makeSuffixFunc(".txt")
fmt.Println(jpgFunc("test"))
fmt.Println(txtFunc("test"))
}
运行结果:
test.jpg
test.txt
例子三:
func calc(base int) (func(int) int, func(int) int) {
add := func(i int) int {
base += i
return base
}
sub := func(i int) int {
base -= i
return base
}
return add, sub
}
func main() {
f1, f2 := calc(10)
fmt.Println(f1(1), f2(2))
fmt.Println(f1(3), f2(4))
fmt.Println(f1(5), f2(6))
}
运行结果:
11 9
12 8
13 7