闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

Function literals are closures: they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible.

What happens with closures running as go-routines?

To bind the current value of v to each closure as it is launched, one must modify the inner loop to create a new variable each iteration. One way is to pass the variable as an argument to the closure.

Even easier is just to create a new variable, using a declaration style that may seem odd but works fine in Go.

for _, val := range values {
	go func() {
	  fmt.Println(val) // loop variable val captured by func literal
  }()
}

// because each iteration of the loop uses the same instance of the val
// so each closure shares that single variable.

To bind the current value of v to each closure as it is launched, one must modify the inner loop to create a new variable each iteration

for _, v := range values {
	go func(u string) {
		fmt.Println(u)
    done <- true
  }(v)
}
type val int
values := []val{1, 2, 3}

func main() {
	for _, val := range values {
		go val.MyMethod()
	}
}

func (v *val) MyMethod() {
	fmt.Println(v)
}

// 0xc000018030
// 0xc000018030
// 0xc000018030

func (v val) MyMethod() {
	fmt.Println(v)
}

// 1
// 2
// 3

复杂闭包场景

fun returnFunction() {
	var outside = "outside";
	fun inner() {
		print outside;
	}
	return inner
}
var fn = returnFunction();
fn();

在这里 inner() 访问了周围函数中在其主体之外声明的一个局部变量,要做到这一点 inner() 必须抓住它锁使用的任何周围变量的引用,以便它们在外层函数返回后仍然存在,我们把这样做的函数称为闭包,为了实现这类函数,需要创建一个数据结构,将函数的代码和它所需要的周围变量捆绑在一起。