您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)Go語(yǔ)言中閉包的示例分析,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
閉包
在函數(shù)編程中經(jīng)常用到閉包,閉包是什?它是怎么產(chǎn)生的及用來(lái)解決什么問(wèn)題呢?先給出閉包的字面定義:閉包是由函數(shù)及其相關(guān)引用環(huán)境組合而成的實(shí)體(即:閉包=函數(shù)+引用環(huán)境)。這個(gè)從字面上很難理解,特別對(duì)于一直使用命令式語(yǔ)言進(jìn)行編程的程序員們。
Go語(yǔ)言中的閉包
先看一個(gè)demo:
func f(i int) func() int { return func() int { i++ return i } }
函數(shù)f返回了一個(gè)函數(shù),返回的這個(gè)函數(shù)就是一個(gè)閉包。這個(gè)函數(shù)中本身是沒(méi)有定義變量i的,而是引用了它所在的環(huán)境(函數(shù)f)中的變量i。
我們?cè)倏匆幌滦Ч?/strong>
c1 := f(0) c2 := f(0) c1() // reference to i, i = 0, return 1 c2() // reference to another i, i = 0, return 1
c1跟c2引用的是不同的環(huán)境,在調(diào)用i++時(shí)修改的不是同一個(gè)i,因此兩次的輸出都是1。函數(shù)f每進(jìn)入一次,就形成了一個(gè)新的環(huán)境,對(duì)應(yīng)的閉包中,函數(shù)都是同一個(gè)函數(shù),環(huán)境卻是引用不同的環(huán)境。
變量i是函數(shù)f中的局部變量,假設(shè)這個(gè)變量是在函數(shù)f的棧中分配的,是不可以的。因?yàn)楹瘮?shù)f返回以后,對(duì)應(yīng)的棧就失效了,f返回的那個(gè)函數(shù)中變量i就引用一個(gè)失效的位置了。所以閉包的環(huán)境中引用的變量不能夠在棧上分配。
escape analyze
在繼續(xù)研究閉包的實(shí)現(xiàn)之前,先看一看Go的一個(gè)語(yǔ)言特性:
func f() *Cursor { var c Cursor c.X = 500 noinline() return &c }
Cursor是一個(gè)結(jié)構(gòu)體,這種寫(xiě)法在C語(yǔ)言中是不允許的,因?yàn)樽兞縞是在棧上分配的,當(dāng)函數(shù)f返回后c的空間就失效了。但是,在Go語(yǔ)言規(guī)范中有說(shuō)明,這種寫(xiě)法在Go語(yǔ)言中合法的。語(yǔ)言會(huì)自動(dòng)地識(shí)別出這種情況并在堆上分配c的內(nèi)存,而不是函數(shù)f的棧上。
為了驗(yàn)證這一點(diǎn),可以觀察函數(shù)f生成的匯編代碼:
MOVQ $type."".Cursor+0(SB),(SP) // 取變量c的類型,也就是Cursor PCDATA $0,$16 PCDATA $1,$0 CALL ,runtime.new(SB) // 調(diào)用new函數(shù),相當(dāng)于new(Cursor) PCDATA $0,$-1 MOVQ 8(SP),AX // 取c.X的地址放到AX寄存器 MOVQ $500,(AX) // 將AX存放的內(nèi)存地址的值賦為500 MOVQ AX,"".~r0+24(FP) ADDQ $16,SP
識(shí)別出變量需要在堆上分配,是由編譯器的一種叫escape analyze的技術(shù)實(shí)現(xiàn)的。
如果輸入命令:
go build --gcflags=-m main.go
可以看到輸出:
注意:最后兩行,標(biāo)識(shí)c逃逸了,被移動(dòng)到堆中。escape analyze可以分析出變量的作用范圍,這是對(duì)垃圾回收很重要的一項(xiàng)技術(shù)。
關(guān)于“Go語(yǔ)言中閉包的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。