日B视频 亚洲,啪啪啪网站一区二区,91色情精品久久,日日噜狠狠色综合久,超碰人妻少妇97在线,999青青视频,亚洲一区二卡,让本一区二区视频,日韩网站推荐

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

詳細(xì)介紹go語言中的閉包的實現(xiàn)

馬哥Linux運維 ? 來源:tiancaiamao ? 作者:tiancaiamao ? 2021-10-20 16:18 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

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

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

Go中的閉包

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

funcf(iint)func()int{
returnfunc()int{
i++
returni
}
}

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

c1:=f(0)
c2:=f(0)
c1()//referencetoi,i=0,return1
c2()//referencetoanotheri,i=0,return1

c1跟c2引用的是不同的環(huán)境,在調(diào)用i++時修改的不是同一個i,因此兩次的輸出都是1。函數(shù)f每進入一次,就形成了一個新的環(huán)境,對應(yīng)的閉包中,函數(shù)都是同一個函數(shù),環(huán)境卻是引用不同的環(huán)境。

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

escape analyze

在繼續(xù)研究閉包的實現(xiàn)之前,先看一看Go的一個語言特性:

funcf()*Cursor{
varcCursor
c.X=500
noinline()
return&c
}

Cursor是一個結(jié)構(gòu)體,這種寫法在C語言中是不允許的,因為變量c是在棧上分配的,當(dāng)函數(shù)f返回后c的空間就失效了。但是,在Go語言規(guī)范中有說明,這種寫法在Go語言中合法的。語言會自動地識別出這種情況并在堆上分配c的內(nèi)存,而不是函數(shù)f的棧上。

為了驗證這一點,可以觀察函數(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
MOVQ8(SP),AX//取c.X的地址放到AX寄存器
MOVQ$500,(AX)//將AX存放的內(nèi)存地址的值賦為500
MOVQAX,"".~r0+24(FP)
ADDQ$16,SP

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

gobuild--gcflags=-mmain.go

可以看到輸出:

./main.gomovedtoheap:c
./main.go&cescapestoheap

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

閉包結(jié)構(gòu)體

回到閉包的實現(xiàn)來,前面說過,閉包是函數(shù)和它所引用的環(huán)境。那么是不是可以表示為一個結(jié)構(gòu)體呢:

typeClosurestruct{
Ffunc()()
i*int
}

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

funcf(iint)func()int{
returnfunc()int{
i++
returni
}
}


MOVQ$type.int+0(SB),(SP)
PCDATA$0,$16
PCDATA$1,$0
CALL,runtime.new(SB)//是不是很熟悉,這一段就是i=new(int)
...
MOVQ$type.struct{Fuintptr;A0*int}+0(SB),(SP)//這個結(jié)構(gòu)體就是閉包的類型
...
CALL,runtime.new(SB)//接下來相當(dāng)于new(Closure)
PCDATA$0,$-1
MOVQ8(SP),AX
NOP,
MOVQ$"".func·001+0(SB),BP
MOVQBP,(AX)//函數(shù)地址賦值給Closure的F部分
NOP,
MOVQ"".&i+16(SP),BP//將堆中new的變量i的地址賦值給Closure的值部分
MOVQBP,8(AX)
MOVQAX,"".~r1+40(FP)
ADDQ$24,SP
RET,

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

小結(jié)

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

轉(zhuǎn)自:

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

編輯:jq
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • C語言
    +關(guān)注

    關(guān)注

    183

    文章

    7646

    瀏覽量

    146204
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4422

    瀏覽量

    67876
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4977

    瀏覽量

    74420
  • go語言
    +關(guān)注

    關(guān)注

    1

    文章

    160

    瀏覽量

    9853

原文標(biāo)題:Golang 閉包的實現(xiàn)

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    Go 語言高并發(fā)服務(wù)設(shè)計與性能調(diào)優(yōu)實戰(zhàn):從萬級到百萬級并發(fā)的演進之路

    在2026年的今天,Go 語言已成為高并發(fā)后端服務(wù)的首選語言。根據(jù) Stack Overflow 最新開發(fā)者調(diào)查: 指標(biāo) 數(shù)據(jù) Go 語言
    發(fā)表于 02-18 19:19

    請問C語言中整形溢出的解決方法有哪些?

    C語言中整形溢出的解決方法有哪些?
    發(fā)表于 12-29 07:33

    單片機c語言中定義字節(jié)怎么定義?

    定義位可以用***it但是定義字節(jié)呢?還有就是比如匯編中的DPTR的DPH和DPL在c語言中怎樣定義的呢?
    發(fā)表于 12-29 06:32

    請問C語言中整形溢出會產(chǎn)生哪些異常行為?

    C語言中整形溢出會產(chǎn)生哪些異常行為?
    發(fā)表于 12-26 07:05

    請問C語言中整形溢出對哪些應(yīng)用場景影響較大?

    C語言中整形溢出對哪些應(yīng)用場景影響較大
    發(fā)表于 12-24 08:24

    Typedef在C語言中的應(yīng)用

    Typedef 在C語言中頻繁用以聲明一個已經(jīng)存在的數(shù)據(jù)類型的同義字。也可以用預(yù)處理器做類似的事。例如,思考一下下面的例子: #define dPS struct s * typedef
    發(fā)表于 12-22 13:53

    低成本TLI4971/TLE4971電流傳感器評估套件——MS2Go與S2Go

    低成本TLI4971/TLE4971電流傳感器評估套件——MS2Go與S2Go 在電子工程師的日常工作中,電流傳感器的評估和應(yīng)用是一個重要的環(huán)節(jié)。今天我們要介紹的是英飛凌(Infineon
    的頭像 發(fā)表于 12-19 16:50 ?1232次閱讀

    C語言中可以嵌套匯編語言嗎?

    請問C語言中可以嵌套匯編語言嗎?
    發(fā)表于 12-15 08:14

    C語言的分支結(jié)構(gòu)介紹

    1.簡單if語句 C語言中的分支結(jié)構(gòu)語句中的if條件語句。 簡單if語句的基本結(jié)構(gòu)如下: 代碼語言:javascript if(表達式) { 執(zhí)行代碼塊; } 其語義是:如果表達式的值為真,則執(zhí)行其后的語句,否則不執(zhí)行該語句。 注意:if()后面沒有分號,直
    發(fā)表于 11-25 07:48

    C語言的常量介紹

    、-13; 實型常量:13.33、-24.4; 字符常量:‘a(chǎn)’、‘M’ 字符串常量:”I love china!” 在C語言中,可以用一個標(biāo)識符來表示一個常量,稱之為符號常量。符號常量在使用之前必須先
    發(fā)表于 11-24 07:12

    房產(chǎn)數(shù)據(jù)平臺安家go獲取地區(qū)列表數(shù)據(jù)的API接口

    ? 在房產(chǎn)數(shù)據(jù)平臺“安家go”中,獲取地區(qū)列表數(shù)據(jù)是一個常見需求,它允許開發(fā)者訪問全國或特定區(qū)域的行政區(qū)劃信息,如省、市、區(qū)縣等。這對于構(gòu)建房產(chǎn)搜索、數(shù)據(jù)分析或地圖應(yīng)用至關(guān)重要。本文將詳細(xì)介紹
    的頭像 發(fā)表于 11-21 14:38 ?511次閱讀
    房產(chǎn)數(shù)據(jù)平臺安家<b class='flag-5'>go</b>獲取地區(qū)列表數(shù)據(jù)的API接口

    C語言的printf基本用法介紹

    也是代碼的一部分,但是它并不會給程序帶來任何影響,編譯器在編譯階段會忽略注釋的內(nèi)容,或者說刪除注釋的內(nèi)容。我在《C語言標(biāo)識符、關(guān)鍵字和注釋》一節(jié)中做了詳細(xì)講解。 3) money 的輸出值并不是
    發(fā)表于 11-12 07:04

    在Linux系統(tǒng)下編譯C語言仿真蜂鳥E203(二)

    運行操作在Makefile中有詳細(xì)介紹 make run_test之后在終端中打印跑分信息如下所示,其跑分為3.05 其打印原理時利用了verilog語言中的打印函數(shù)實現(xiàn)的: 在u
    發(fā)表于 10-24 13:38

    Windows環(huán)境下32位匯編語言中文資料

    電子發(fā)燒友網(wǎng)站提供《Windows環(huán)境下32位匯編語言中文資料.rar》資料免費下載
    發(fā)表于 06-30 15:14 ?0次下載

    提高篇——C語言核心技術(shù)(中文版)

    嚴(yán)謹(jǐn)?shù)男g(shù)語表介紹C語言;第二部分描述標(biāo)準(zhǔn)鏈接庫;第三部分介紹GNU軟件中常用的編譯和測試工具。 獲取完整文檔資料可下載附件哦?。。。∪绻麅?nèi)容有幫助可以關(guān)注、點贊、評論支持一下哦~
    發(fā)表于 06-13 16:39
    太白县| 铁力市| 阿尔山市| 新竹市| 托里县| 宁远县| 汕头市| 阜康市| 卢氏县| 岳普湖县| 榆社县| 连云港市| 深圳市| 彰武县| 闸北区| 洱源县| 蒙自县| 阜新| 新郑市| 北票市| 关岭| 忻州市| 鱼台县| 南阳市| 平昌县| 襄汾县| 绵阳市| 女性| 漯河市| 广昌县| 龙井市| 静海县| 磐石市| 通化市| 行唐县| 贡山| 华池县| 青川县| 兰考县| 庄浪县| 什邡市|