日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

golang反编译_【Golang】脱胎换骨的defer(一)

發(fā)布時間:2023/12/2 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 golang反编译_【Golang】脱胎换骨的defer(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Go語言的defer是一個很方便的機制,能夠把某些函數(shù)調(diào)用推遲到當前函數(shù)返回前才實際執(zhí)行。我們可以很方便的用defer關(guān)閉一個打開的文件、釋放一個Redis連接,或者解鎖一個Mutex。而且Go語言在設(shè)計上保證,即使發(fā)生panic,所有的defer調(diào)用也能夠被執(zhí)行。不過多個defer函數(shù)是按照定義順序倒序執(zhí)行的。 我們在公眾號有一篇文章:

【Golang】脫胎換骨的defer?mp.weixin.qq.com

內(nèi)容有點兒多,篇幅有點兒長,所以在這里我們打算拆分成四篇文章,每一篇專注一兩個主要問題,可能會好消化些吧~

(一)“ defer如何延遲,因何倒序?”

(二)“ defer函數(shù)怎樣傳參?”

(三)“ defer+閉包,再多套幾層,你還hold住嗎?”

(四)“ 都說defer1.12性能有坑,那坑從何來?又該怎么填?”

func f1() {defer A()// code to do something }

像這樣一段代碼,在Go1.12中編譯后的偽指令是這樣的(源碼結(jié)合反編譯整理出的偽代碼,幫助理解~_~):

func f1() {r := runtime.deferproc(0, A) // 經(jīng)過recover返回時r為1,否則為0if r > 0 {goto ret}// code to do somethingruntime.deferreturn()return ret:runtime.deferreturn() }

其中與defer指令相關(guān)的有兩個部分。第一部分是deferproc,它負責保存要執(zhí)行的函數(shù)信息,我們稱之為defer“注冊”。

func deferproc(siz int32, fn *funcval)

從函數(shù)原型來看,deferproc函數(shù)有兩個參數(shù),第一個是被注冊的defer函數(shù)的參數(shù)加返回值共占多少字節(jié);第二個參數(shù)是一個runtime.funcval結(jié)構(gòu)體的指針,也就是一個Function Value。對Function Value感興趣,可以看看這個:

網(wǎng)頁鏈接?mp.weixin.qq.com

與defer指令相關(guān)的第二部分就是deferreturn,它被編譯器插入到函數(shù)返回以前調(diào)用,負責執(zhí)行已經(jīng)注冊的defer函數(shù)。所以defer函數(shù)之所以能延遲到函數(shù)返回前執(zhí)行,就是因為先注冊,后調(diào)用。

再來看看defer函數(shù)為什么會倒序執(zhí)行。defer注冊信息會保存到defer鏈表。每個goroutine在運行時都對應一個runtime.g結(jié)構(gòu)體,其中有一個_defer字段,保存的就是defer鏈表的頭指針。

deferproc新注冊的defr信息會添加到鏈表頭。deferreturn執(zhí)行時也從鏈表頭開始,所以defer才會表現(xiàn)為倒序執(zhí)行。

理解了這些,就可以繼續(xù)細化,看看defer注冊時保存了什么信息,defer鏈表中每個元素究竟是什么結(jié)構(gòu)了。

type _defer struct {siz int32started boolsp uintptr // sp at time of deferpc uintptrfn *funcval_panic *_panic // panic that is running deferlink *_defer}

siz:由deferproc第一個參數(shù)傳入,就是defer函數(shù)參數(shù)加返回值的總大小。這段空間會直接分配在_defer結(jié)構(gòu)體后面,用于在注冊時保存給defer函數(shù)傳入的參數(shù),并在執(zhí)行時直接拷貝到defer函數(shù)的調(diào)用者棧上。

started :標識defer函數(shù)是否已經(jīng)開始執(zhí)行;

sp:就是注冊defer函數(shù)的函數(shù)棧指針;

pc:是deferproc函數(shù)返回后要繼續(xù)執(zhí)行的指令地址;

fn:由deferproc的第二個參數(shù)傳入,也就是被注冊的defer函數(shù);

_panic:是觸發(fā)defer函數(shù)執(zhí)行的panic指針,正常流程執(zhí)行defer時它就是nil;

link:自然是鏈到之前注冊的那個_defer結(jié)構(gòu)體。

網(wǎng)頁鏈接?mp.weixin.qq.com

總結(jié)

以上是生活随笔為你收集整理的golang反编译_【Golang】脱胎换骨的defer(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。