Go语言基础-闭包 | 青训营笔记

67 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天

闭包的概念

闭包(Closure)是引用了自由变量的函数,这个函数存储了一个函数和与该函数相关联的函数。

举例

[官方文档](Go by Example: Closures)

// Go supports [_anonymous functions_](https://en.wikipedia.org/wiki/Anonymous_function),
// which can form <a href="https://en.wikipedia.org/wiki/Closure_(computer_science)"><em>closures</em></a>.
// Anonymous functions are useful when you want to define
// a function inline without having to name it.

package main

import "fmt"

// This function `intSeq` returns another function, which
// we define anonymously in the body of `intSeq`. The
// returned function _closes over_ the variable `i` to
// form a closure.
func intSeq() func() int {
	i := 0
	return func() int {
		i++
		return i
	}
}

func main() {

	// We call `intSeq`, assigning the result (a function)
	// to `nextInt`. This function value captures its
	// own `i` value, which will be updated each time
	// we call `nextInt`.
	nextInt := intSeq()

	// See the effect of the closure by calling `nextInt`
	// a few times.
	fmt.Println(nextInt())
	fmt.Println(nextInt())
	fmt.Println(nextInt())

	// To confirm that the state is unique to that
	// particular function, create and test a new one.
	newInts := intSeq()
	fmt.Println(newInts())
}

分析

观察函数inSeq(),发现该函数的内部定义了一个变量i,它将返回一个匿名函数,这个函数持有对外部变量i的引用。

程序入口函数处定义了两个变量nextIntnewInts,它们都分别持有对intSeq()函数中内部匿名函数的引用,执行这段程序,结果为:

1
2
3
1

可以发现,每次执行nextInt(),也就是inSeq()的内部匿名函数时,输出的结果都为上一次执行结果的+1,变量i并没有被回收,而是保留了下来供内部的匿名函数使用。
nextInt就是我们创建的一个闭包,这个闭包保留了一些状态,在这个例子中,状态就是变量i
因此newInts也是一个闭包,但这个闭包是重新创建的,并不与闭包nextInt共享状态,所以它的输出结果就是1

总结

  • 如果一个函数用到了它作用域外面的变量,那么这个变量和这个函数之间的环境就叫闭包。
  • 能够读取其他函数内部变量的函数,就是闭包。(内部的匿名函数持有其外部变量)
  • 闭包是一个有状态的函数。

如有错误或疏漏,还望海涵。