久久国产乱子伦精品免费M,亚洲一区二区三区91,欧美国产在线视频,国产精品视频久久

Golang 閉包的實現

Golang 閉包的實現

什么是閉包?什么場景下會用閉包?本文對?go 語言中的閉包做了詳細介紹。

閉包是由函數及其相關引用環境組合而成的實體(即:閉包=函數+引用環境)。

Go中的閉包

閉包是函數式語言中的概念,沒有研究過函數式語言的用戶可能很難理解閉包的強大,相關的概念超出了本書的范圍。Go語言是支持閉包的,這里只是簡單地講一下在Go語言中閉包是如何實現的。

Golang 閉包的實現

函數f返回了一個函數,返回的這個函數,返回的這個函數就是一個閉包。這個函數中本身是沒有定義變量i的,而是引用了它所在的環境(函數f)中的變量i。

Golang 閉包的實現

c1跟c2引用的是不同的環境,在調用i++時修改的不是同一個i,因此兩次的輸出都是1。函數f每進入一次,就形成了一個新的環境,對應的閉包中,函數都是同一個函數,環境卻是引用不同的環境。

變量i是函數f中的局部變量,假設這個變量是在函數f的棧中分配的,是不可以的。因為函數f返回以后,對應的棧就失效了,f返回的那個函數中變量i就引用一個失效的位置了。所以閉包的環境中引用的變量不能夠在棧上分配。

escape analyze

在繼續研究閉包的實現之前,先看一看Go的一個語言特性:

Golang 閉包的實現

Cursor是一個結構體,這種寫法在C語言中是不允許的,因為變量c是在棧上分配的,當函數f返回后c的空間就失效了。但是,在Go語言規范中有說明,這種寫法在Go語言中合法的。語言會自動地識別出這種情況并在堆上分配c的內存,而不是函數f的棧上。

為了驗證這一點,可以觀察函數f生成的匯編代碼:

Golang 閉包的實現

識別出變量需要在堆上分配,是由編譯器的一種叫escape analyze的技術實現的。如果輸入命令:

Golang 閉包的實現

可以看到輸出:

Golang 閉包的實現

表示c逃逸了,被移到堆中。escape analyze可以分析出變量的作用范圍,這是對垃圾回收很重要的一項技術。

閉包結構體

回到閉包的實現來,前面說過,閉包是函數和它所引用的環境。那么是不是可以表示為一個結構體呢:

Golang 閉包的實現

事實上,Go在底層確實就是這樣表示一個閉包的。讓我們看一下匯編代碼:

Golang 閉包的實現

其中func·001是另一個函數的函數地址,也就是f返回的那個函數。

小結

  1. Go語言支持閉包
  2. Go語言能通過escape analyze識別出變量的作用域,自動將變量在堆上分配。將閉包環境變量在堆上分配是Go實現閉包的基礎。
  3. 返回閉包時并不是單純返回一個函數,而是返回了一個結構體,記錄下函數返回地址和引用的環境中的變量地址。

轉自:tiancaiamao.gitbooks.io/go-internals/content/zh/03.6.html

文章轉載:Go開發大全(版權歸原作者所有,侵刪)

相關新聞

歷經多年發展,已成為國內好評如潮的Linux云計算運維、SRE、Devops、網絡安全、云原生、Go、Python開發專業人才培訓機構!

    1. 主站蜘蛛池模板: 南岸区| 巴林右旗| 扬中市| 桑日县| 东乡族自治县| 渝北区| 永清县| 白河县| 南宫市| 乐亭县| 苏尼特右旗| 女性| 奎屯市| 昂仁县| 太仆寺旗| 徐闻县| 健康| 开封市| 霍林郭勒市| 三亚市| 康定县| 周至县| 礼泉县| 潞西市| 林周县| 武隆县| 宜黄县| 张家港市| 安丘市| 万全县| 高雄市| 蓝田县| 蓬莱市| 湘西| 桑植县| 凤冈县| 岫岩| 麟游县| 萨迦县| 达州市| 西乡县|