GoLang之闭包

文章目录

  • GoLang之闭包
    • 1.闭包、自由变量定义
    • 2.普通函数不能引用main函数里的变量
    • 3.函数赋给变量不加括号是赋类型
    • 4.函数赋给变量加括号是调用函数
    • 4.%T查看函数类型
    • 5.函数类型变量输出结果是指针
    • 6.改变变量值后地址不会变
    • 7.匿名函数里会改变到全局变量的值但不会改变地址
    • 8.匿名函数作为返回值“:=”声明后可再当函数使用
    • 9.匿名函数作为返回值被调用后可去原函数调用变量
    • 10.匿名函数作为返回值var声明后可再当函数使用
    • 11.闭包实例汇总

GoLang之闭包

1.闭包、自由变量定义

闭包的应该都听过,但到底什么是闭包呢?
闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)。
“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
维基百科讲,闭包(Closure),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
支持闭包的语法可以发现一个特点,他们都有垃圾回收(GC)机制

image-20220107195202017

image-20220107195225021

image-20220107195244105

2.普通函数不能引用main函数里的变量

GoLang之闭包_第1张图片

函数也是一种类型

3.函数赋给变量不加括号是赋类型


func a() {
	
	return
}

func main() {
	c := a
	fmt.Println(c)
}

4.函数赋给变量加括号是调用函数

GoLang之闭包_第2张图片

报错是因为该函数没有返回值

GoLang之闭包_第3张图片

4.%T查看函数类型

GoLang之闭包_第4张图片GoLang之闭包_第5张图片

5.函数类型变量输出结果是指针

GoLang之闭包_第6张图片

6.改变变量值后地址不会变

GoLang之闭包_第7张图片

7.匿名函数里会改变到全局变量的值但不会改变地址

GoLang之闭包_第8张图片

8.匿名函数作为返回值“:=”声明后可再当函数使用

GoLang之闭包_第9张图片
GoLang之闭包_第10张图片
GoLang之闭包_第11张图片

GoLang之闭包_第12张图片

9.匿名函数作为返回值被调用后可去原函数调用变量

GoLang之闭包_第13张图片
GoLang之闭包_第14张图片
GoLang之闭包_第15张图片

10.匿名函数作为返回值var声明后可再当函数使用


func A(i int) {
	i++
	fmt.Println(i)
}
func C() func(a int) {
	return A
}

func main() {
	var f1 func() func(a int) = C
	fmt.Println(f1())//0x7dc560

	var f2 func(a int) = C()
	f2(1)//2
}

GoLang之闭包_第16张图片

11.闭包实例汇总

func a() {
	i := 0
	func() int {
		i++
		fmt.Println(i)
		return i
	}()
	return
}

func main() {
	a() //输出:1
	a() //输出 1
}


func a() {
	i := 0
	func() int {
		i++
		fmt.Println(i)
		return i
	}()
	return
}

func main() {
	c := a
	c()//输出:1
	c()//输出:1
	c()//输出:1
}


func a() func() int {
	i := 0
	b := func() int {
		i++
		fmt.Println(i)
		return i
	}
	return b
}

func main() {
	c := a()
	c()//输出 1
	c()//输出 2
	c()//输出 3
}


func a() func() int {
	i := 0
	b := func() int {
		i++
		fmt.Println(i)
		return i
	}
	return b
}

func main() {
	a()//无任何输出
}


func a() func() int {
	i := 0
	b := func() int {
		i++

		fmt.Println(i)
		return i
	}
	return b
}

func main() {
	c := a()
	c() //输出 1
	c() //输出 2
	c() //输出 3
	d := a()
	d()//1
	d()//2
	d()//3
}

GoLang之闭包_第17张图片

GoLang之闭包_第18张图片

GoLang之闭包_第19张图片

以下程序中的匿名函数由于在函数体内部引用了外部的自由变量num而形成了闭包。闭包每次对num变量的加1操作都是对变量num引用的修改。
可以看出,物理地址没有发生变化,但是数值确发生变化,同时在第一个匿名函数中(闭包) 自变量n 发生变化,之后,n并没有重置,而是在基于保持该值,进入了第二个匿名函数中(闭包),n的数值继续发生变化,但是物理地址还是没有发生变化。
说明,在同一个作用域中(一个函数中,此处为 main(),当然可以为其他自定义的函数 ),闭包中的变量不会重置。

GoLang之闭包_第20张图片

GoLang之闭包_第21张图片

GoLang之闭包_第22张图片

GoLang之闭包_第23张图片

GoLang之闭包_第24张图片

你可能感兴趣的:(GoLang,golang,开发语言,后端)