闭包和匿名函数还傻傻分不清楚吗

1,033 阅读1分钟

结合很多资料以及自己的理解和案例分析,区分匿名函数与闭包的作用和意义

匿名函数:没有名字的函数。是为了开辟封闭的变量作用域环境。用于构造闭包

以下是4种构造匿名函数的方法:

func main() {
    // 方法1
	func() {
		fmt.Println("hello1")
	}()
	// 方法2
	fn := func() {
		fmt.Println("hello2")
	}
	fn()
	// 方法3
	fn1 := func(str string) {
		fmt.Println(str)
	}
	fn1("hello3")
	// 方法4
	fn2 := func() string {
		return "hello4"
	}
	fmt.Println(fn2())
}

/*
    hello1
    hello2
    hello3
    hello4
*/

闭包:利用匿名函数实现。可以在函数外部访问函数的变量,函数调用返回后一个没有释放资源的栈区。不需传值也在创建函数中使用自己的私有变量。闭包返回的是一个复合结构:包括匿名函数的地址以及变量的地址

优点:减少代码量,使这些局部变量始终保存着内存中,避免使用全局变量

缺点:这些局部变量不会立即销毁,浪费内存。会出现闭包的延迟

type Func func(x int) int // 定义函数类型
// 闭包
func A() Func { 
	var i = 1
	return func(a int) int{   // 匿名函数
		i++
		return a+i
	}
}

func main() {
	res := A() // res = A.func1 
    fmt.Println(res(1)) // A.func1(1) = 3
	fmt.Println(res(1)) // A.func1(1) = 4
}

从以上案例可以看到A是一个闭包函数,main函数中的res调用闭包A之后,返回闭包的定义。按照常规函数调用A的栈此时已经释放,但是作为闭包的A返回了匿名函数的地址和局部变量i,A没有释放自己的栈区域。res(1)实际进行闭包的执行。

我们也看到,闭包可以使用匿名函数来实现。当然也可以是实名函数或者lambda表达式