golang闭包

函数类型是可以作为参数和返回值使用的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func main() {
	ret := f2(f1, 10, 20)
	f3(ret)
	//或者f3(f2(f1, 10, 20))
}

func f1(x, y int) int {
	fmt.Println("this is f2")
	return x + y
}

func f2(x func(int, int) int, m, n int) func() {
	tmp := func() {
		a1 := x(m, n)
		fmt.Println(a1)
	}
	return tmp
}

func f3(f func()) {
	fmt.Println("this is f3")
	f()
}

将f2作为两个函数的中转站,f3只能接收无参无返回值,但是我们只有一个f1,是有参的,所以定义一个f2让它返回一个无参函数类型的返回值,将f1和f1的参数传进去,这样通过调用f2就可以同时调用f3,并且在f2中使用匿名函数调用f1,这样就可以通过f3(f2(f1,10,20))来实现f3调用f1

闭包的概念就是一个函数除了调用本身内部的变量还可以调用函数外部作用域的变量(其他函数中的局部变量)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func adder(x int) func (int) int{
	return func(y int) int{
		x +=y
		return x
	}
}

func main(){
	a1:=adder(100)
	y:=a1(100)
	fmt.Println(y)
}

平时的函数,你调用它就只需要看它内部有哪些变量,但是闭包通过匿名函数可以实现我在函数中使用x并不需要定义,它直接在匿名函数上一级函数进行定义了,匿名变量作为返回值就可以对上一级的函数变量进行引用

这样示例一就实现了函数一的参数是一个无参无返回值的函数类型,但是只有一个有参有返回值的函数二,通过定义一个函数三,将有参有返回值的函数二和它需要的变量作为参数传进去,然后直接返回一个无参无返回值的匿名函数,在匿名函数中调用有参函数二,这样在需要的地方只需要调用中转函数三并将有参函数二传进去,就可以获得一个无参无返回值但是调用了有参函数二的函数类型,可以作为函数一的参数使用了

闭包=函数 + 函数上一级作用域的变量的引用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
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)) //11 9
	fmt.Println(f1(3),f2(4)) //12 8
}

add和sub函数调用了外部的base变量,calc函数只调用了一次,即base只初始化了一次(10),第一次先调用add就是寻找外部的变量,增加后返回,但是此时base值已经改变(变为11),然后进行sub函数,重新寻找base,此时为11(11-2),无论进行多少次都是在上次的基础上进行计算,不会重新初始化为10了

Licensed under CC BY-NC-SA 4.0