閉包的體現形式,能常就是用函數返回另一個函數
先列出一些閉包的實例:
代碼1:
package main import "fmt" func adder() func(int) int { sum := 0 return func(x int) int { sum += x return sum } } func main() { pos, neg := adder(), adder() for i := 0; i < 10; i++ { fmt.Println( pos(i), neg(-2*i), ) } }
執行后輸出如下:
0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90
代碼2:
package main import "fmt" func main() { var flist []func() for i := 0; i < 3; i++ { flist = append(flist, func() { fmt.Println(i) }) } for _, f := range flist { f() } }
執行輸出:
3
3
3
代碼3:
package main import "fmt" func main() { var flist []func() for i := 0; i < 3; i++ { i := i //給i變量重新賦值, fmt.Println(i) flist = append(flist, func() { fmt.Println(i) }) } for _, f := range flist { f() } }
執行輸出:
0
1
2
0
1
2
在網上看了不少資料,最后發現許式偉 的《Go語言編程》這本書上對閉包已經概括的挺好,就直接摘錄在下面:
閉包的概念:是可以包含自由(未綁定到特定對象)變量的代碼塊,這些變量不在這個代碼塊內或者任何全局上下文中定義,而是在定義代碼塊的環境中定義。要執行的代碼塊(由於自由變量包含在代碼塊中,所以這些自由變量以及它們引用的對象沒有被釋放)為自由變量提供綁定的計算環境(作用域)。
閉包的價值 : 閉包的價值在於可以作為函數對象或者匿名函數,對於類型系統而言,這意味着不僅要表示數據還要表示代碼。支持閉包的多數語言都將函數作為第一級對象,就是說這些函數可以存儲到變量中作為參數傳遞給其他函數,最重要的是能夠被函數動態創建和返回。
Go語言中的閉包同樣也會引用到函數外的變量。閉包的實現確保只要閉包還被使用,那么被閉包引用的變量會一直存在。
總結:
閉包並不是一門編程語言不可缺少的功能,但閉包的表現形式一般是以匿名函數的方式出現,就象上面說到的,能夠動態靈活的創建以及傳遞,體現出函數式編程的特點。所以在一些場合,我們就多了一種編碼方式的選擇,適當的使用閉包可以使得我們的代碼簡潔高效。
使用閉包的注意點
由於閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包
最近在網上看到一篇講閉包,感覺講得簡單明了,一針見血 https://www.cnblogs.com/cxying93/p/6103375.html