go:匿名函數與閉包

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

一、匿名函數

  定義:沒有函數名的函數。

  作用:在go語言中目前瞭解的作用就是用於構成閉包。

  *註:由於js不存在塊級範圍,故匿名函數常用來包含代碼以不汙染全域命名空間,運行後銷毀環境。

    ----來自知乎回答:http://www.zhihu.com/question/34649602

  使用方法及其原理請參考:http://www.cnblogs.com/chenxianbin89/archive/2010/01/28/1658392.html

 

  使用舉例

  (1)

a := func() {fmt.Println(1)}a() //輸出:1

  (2)帶參數

b := func(arg int) {fmt.Println(arg)}b(2) //輸出:2(func(arg int) {fmt.Println(arg)})(3) //輸出:3

  (3)帶傳回值

c := func() int {fmt.Println(4)return 5}d := c() //列印輸出4,並將5賦值給dfmt.Println(d)

  

二、閉包(closure)

  

  閉包的理解參考:http://www.cnblogs.com/mzwr1982/archive/2012/05/20/2509295.html 

  閉包的用途參考:http://blog.csdn.net/sunlylorn/article/details/6534610

        和   http://www.cnblogs.com/rainman/archive/2009/05/04/1448899.html

  簡單來說:

  因為把返回的函數賦給了一個變數,雖然函數在執行完一瞬間會銷毀其執行環境,

  但是如果有閉包的話,閉包會儲存外部函數的使用中的物件(變數),所以如果不把對閉包的引用消除掉,

  閉包會一直存在記憶體中,垃圾收集器不會銷毀閉包佔用的記憶體。

    ----來自知乎回答http://www.zhihu.com/question/34649602

  使用舉例

  (1)

 

//函數A是一個不帶參數,傳回值是一個匿名函數,且該函數//帶有一個int型別參數,傳回值為一個int類型func A() func(aa int) int {sum := 0return func(cc int) int {sum += ccfmt.Println("aa=", aa, "bb=", bb, "sum=", sum)return sum}}//編譯錯誤,提示aa未定義

 

  實際上func(aa int) int只是函數A的傳回值,在這裡給參數取名無任何作用,反而會影響代碼閱讀,直接用func(int) int 即可。

  更正後:

func A() func(int) int {sum := 0return func(bb int) int {sum += bbfmt.Println("bb=", bb, "\tsum=", sum)return sum}}

  調用1:

func main() {a := A()//定義變數a,並將函數A的傳回值賦給ab := a(4)fmt.Println(b)}/***    輸出:   **    bb= 4   sum= 4**    4*/

  調用2:

func main() {a := A()a(0)a(1)a(5)}/***  輸出:**  bb= 0 sum= 0**  bb= 1 sum= 1**  bb= 5 sum= 6*/

  以上調用通過閉包實現了sum的累加

  調用3:

func main() {a := A()c := A()a(0)a(5)c(10)c(20)}/***  輸出:**  bb= 0 sum= 0**  bb= 5 sum= 5**  bb= 10 sum= 10**  bb= 20 sum= 30   */

  可以看出,上例中調用了兩次函數A,構成了兩個閉包,這兩個閉包維護的變數sum不是同一個變數。

  (2)

func B() []func() {b := make([]func(), 3, 3)for i := 0; i < 3; i++ {b[i] = func() {fmt.Println(i)}}return b}func main() {c := B()c[0]()c[1]()c[2]()}/***  輸出:**  3**  3**  3*/

  閉包通過引用的方式使用外部函數的變數。

  上例中只調用了一次函數B,構成一個閉包,i 在外部函數B中定義,所以閉包維護該變數 i ,c[0]、c[1]、c[2]中的 i 都是閉包中 i 的引用。

  因此執行c:=B()後,i 的值已經變為3,故再調用c[0]()時的輸出是3而不是0。

 

  可作如下修改:

func B() []func() {b := make([]func(), 3, 3)for i := 0; i < 3; i++ {b[i] = (func(j int) func() {return func() {fmt.Println(j)}})(i)}return b}func main() {c := B()c[0]()c[1]()c[2]()}/***    輸出:**        0**        1**        2*/

  以上修改可能沒有什麼實際意義,此處僅為說明問題使用。

 

  在使用defer的時候可能出現類似問題,需要注意:

for j := 0; j < 2; j++ {defer (func() {fmt.Println(j)})()}/***    輸出:    **    2    **    2*/

  

 

  

  

 

  

  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.