閉包
1,概念
閉包是函數式編程中一個重要的概念。要了解閉包,首先要先了解幾個數學中拓撲學的集合概念,閉集,開集,閉包。
閉集與開集
一般的,有a和b是已知實數,我們把集合[a,b],這樣的集合稱爲閉集,把(a,b)這樣的集合稱爲開集。
由以上結論,若設集合A = (a,b) ,b = {a,b}.這裏A是一個範圍,B是由兩個數構成的集合。那麼可以得到
A U B = [a, b] 是一個閉集。
通俗的講,開集 + 邊界 = 閉集
閉包
在上述基礎上,我們把A U B稱爲A的閉包,可見閉包是一個閉集。由此,我們可以知道閉包是包括開集及其邊界的一個集合。
2,函數編程中的閉包
函數編程中,我們把在函數內部聲明的函數叫做這個函數閉包。
基於閉包概念,可知函數的閉包應該包含函數與及其不包含的邊界。這種哲學反映在在了函數的變量上,閉包可以使用函數中的變量,而且是函數中的最終變量。說明閉包包含了函數裏面所有的運算,所以叫閉包嘛。
接下來看golang中閉包的長相
func main() {
A()()
}
func A() func() {
return func() {
fmt.Print("這是一個閉包")
}
}
從上面看,返回的函數就是函數A的閉包。
接下來需要與閉包概念統一,即閉包應包含函數A中的所有操作。
func main() {
A()()
}
func A() func() {
b := 1
a := func() {
fmt.Print("閉包中的變量", b)
}
b = 3
return a
}
// 閉包中的變量3
顯然可以理解成閉包需要包含函數A中的所有操作,所以這個b應該是函數執行完畢後的值,所以b需要是3
接下來再看一段代碼:
func main() {
A()()
}
func A() func()func() {
b := 1
a := func() func(){
b = 2
return func() {
fmt.Println("這是一個閉包", b)
}
b = 5
}
b = 3
return a
}
//這是一個閉包5
閉包,對於A來說,func()func()纔是A的閉包,我們暫時不把閉包的閉包也是他的閉包拿出來講。如上的程序,func()func()的閉包是func(),func()中的這個b是從func()func()中拿的,那func()func()的變量就要去A中拿,所以出現了閉包中的變量就近原則。
通過上述基礎,我們知道了爲什麼閉包要這樣設計,那麼這樣的設計是怎麼做的呢?這個再網上有很多資料,包括作用域鏈,閉包與自定義變量的存儲再堆上,這些都是爲了實現閉包的設計。
如果有錯,歡迎指出。