golang反编译_【Golang】脱胎换骨的defer(一)
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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: laravel 控制器中使用中间件_在
- 下一篇: cad填充图案乱理石_CAD软件中如何自