Contents

Closure

Contents

闭包

闭包就是一个函数和与其相关的引用环境组合的一个整体

闭包就是返回的匿名函数+匿名函数以外的变量sum

感受:匿名函数中引用的那个变量会一直保存在内存中,可以一直使用

函数在创建的时候会创建两个对象,一个是函数对象本身,另一个是作用域链对象 函数在调用的时候会创建一个执行环境对象(活动对象)

  • 返回值是内存函数(实际是内层函数地址)
  • 内层函数涉及到方法中的i
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import "fmt"

func main() {
	f := getSum()

	fmt.Println(getSum())
	fmt.Println(f(100))
	fmt.Println(f(2))
	fmt.Println(f(3))
}

func getSum() func(int) int {
	var sum = 0
	return func(num int) int {
		sum = num+sum
		return sum
	}
}
//===-==

0x49aa70
100
102
105

注意

1、中使用的变量/参数会一直保存在内存中,所以会一直使用—>意味着闭包不可滥用

2、闭包的用处

(1)可以读取函数内部的变量

(2)让这些变量始终保持在内存中

(3)封装对象的私有属性和私有方法

(4)延长变量的生命周期

3、为什么要使用闭包

定义了一个全局变量,每次累加都是更新这个全局变量,but编程语言有一条不成文的铁律,就是尽可能少定义全局变量

  1. 全局变量难以控制,可以在任何地方进行读写,意味着可能会被不相干的程序改写。
  2. 回收机制会每隔一段时间进行一次回收操作,释放不需要被占用的内存。一般局部变量(定义在函数中的变量),在函数调用完成后与之对应的执行环境会被推出执行栈。而全局变量因为随时可以被任何程序在任何地方读写,所以回收机制很难统计何时需要释放全局变量所占用的内存,也就导致全局变量一般是在全局执行环境被销毁时才会释放,占用内存的生命周期长。

(当我们需要重复使用一个对象,但又想保护这个对象不被其他代码污染。)

意义

Go 函数可以是一个闭包。闭包是一个函数值,它引用了函数体之外的变量。 这个函数可以对这个引用的变量进行访问和赋值;换句话说这个函数被“绑定”在这个变量上。

我的不靠谱的理解,一个闭包相当于一个类的实例,函数体之外的变量相当于这个实例存储的变量。

没有闭包的时候,函数就是一次性买卖,函数执行完毕后就无法再更改函数中变量的值(应该是内存释放了);有了闭包后函数就成为了一个变量的值,只要变量没被释放,函数就会一直处于存活并独享的状态,因此可以后期更改函数中变量的值(因为这样就不会被go给回收内存了,会一直缓存在那里)。

从上面的示例中我们可以看出闭包的两个核心作用:

  • 在函数外部访问函数内部变量成为可能
  • 函数内部变量离开其作用域后始终保持在内存中而不被销毁