欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

defer關鍵字、panic和recover的示例分析-創(chuàng)新互聯(lián)

這篇文章給大家介紹defer關鍵字、panic和recover的示例分析,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

阿勒泰ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:028-86922220(備注:SSL證書合作)期待與您的合作!

defer關鍵字

defer關鍵字可以讓函數(shù)或語句延遲到函數(shù)語句塊的最結尾時,即即將退出函數(shù)時執(zhí)行,即便函數(shù)中途報錯結束、即便已經panic()、即便函數(shù)已經return了,也都會執(zhí)行defer所推遲的對象。

其實defer的本質是,當在某個函數(shù)中使用了defer關鍵字,則創(chuàng)建一個獨立的defer棧幀,并將該defer語句壓入棧中,同時將其使用的相關變量也拷貝到該棧幀中(顯然是按值拷貝的)。因為棧是LIFO方式,所以先壓棧的后執(zhí)行。因為是獨立的棧幀,所以即使調用者函數(shù)已經返回或報錯,也一樣能在它們之后進入defer棧幀去執(zhí)行。

例如:

func main() {    a()} func a() { println("in a") defer b() // 將b()壓入defer棧中 println("leaving a") //到了這里才會執(zhí)行b() } func b() { println("in b") println("leaving b")}

上面將輸出:

in aleaving a in bleaving b

即便是函數(shù)已經報錯,或函數(shù)已經return返回,defer的對象也會在函數(shù)退出前的最后一刻執(zhí)行。

func a() TYPE{    ...CODE... defer b()        ...CODE... // 函數(shù)執(zhí)行出了錯誤 return args // 函數(shù)b()都會在這里執(zhí)行 }

但注意,由于Go的作用域采用的是詞法作用域,defer的定義位置決定了它推遲對象能看見的變量值,而不是推遲對象被調用時所能看見的值。

例如:

package main var x = 10 func main() {    a()} func a() { println("start a:",x) // 輸出10 x = 20 defer b(x) // 壓棧,并按值拷貝20到棧中 x = 30 println("leaving a:",x) // 輸出30 // 調用defer延遲的對象b(),輸出20 } func b(x int) { println("start b:",x)}

比較下面的defer:

package main var x = 10 func main() {    a()} func a() int { println("start a:", x) // 輸出10 x = 20 defer func() { // 壓棧,但并未傳值,所以內部引用x println("in defer:", x) // 輸出30 }()    x = 30 println("leaving a:", x) // 輸出30 return x}

上面defer推遲的匿名函數(shù)輸出的值是30,它看見的不應該是20嗎?先再改成下面的:

package main var x = 10 func main() {    a()} func a() int { println("start a:", x) // 輸出10 x = 20 defer func(x int) { println("in defer:", x) // 輸出20 }(x)    x = 30 println("leaving a:", x) // 輸出30 return x}

這個defer推遲的對象中看見的卻是20,這和第一種defer b(x)是相同的。

原因在于defer推遲的如果是函數(shù),它直接就在它的定義位置處評估好參數(shù)、變量。該拷貝傳值的拷貝傳值,該指針相見的指針相見。所以,對于第(1)和第(3)種情況,在defer的定義位置處,就將x=20拷貝給了推遲的函數(shù)參數(shù),所以函數(shù)內部操作的一直是x的副本。而第二種情況則是直接指向它所看見的x=20那個變量,則個變量是全局變量,當執(zhí)行x=30的時候會將其值修改,到執(zhí)行defer推遲的對象時,它指向的x的值已經是修改過的。

再看下面這個例子,將defer放進一個語句塊中,并在這個語句塊中新聲明一個同名變量x:

func a() int { println("start a:", x) // 輸出10 x = 20 {        x := 40 defer func() { println("in defer:", x) // 輸出40 }()    }    x = 30 println("leaving a:", x) // 輸出30 return x}

上面的defer定義在語句塊中,它能看見的x是語句塊中x=40,它的x指向的是語句塊中的x。另一方面,當語句塊結束時,x=40的x會消失,但由于defer的函數(shù)中仍有x指向40這個值,所以40這個值仍被defer的函數(shù)引用著,它直到defer執(zhí)行完之后才會被GC回收。所以defer的函數(shù)在執(zhí)行的時候,仍然會輸出40。

如果語句塊內有多個defer,則defer的對象以LIFO(last in first out)的方式執(zhí)行,也就是說,先定義的defer后執(zhí)行。

func main() { println("start...") defer println("1") defer println("2") defer println("3") defer println("4") println("end...")}

將輸出:

start... end... 4 3 2 1

defer有什么用呢?一般用來做善后操作,例如清理垃圾、釋放資源,無論是否報錯都執(zhí)行defer對象。另一方面,defer可以讓這些善后操作的語句和開始語句放在一起,無論在可讀性上還是安全性上都很有改善,畢竟寫完開始語句就可以直接寫defer語句,永遠也不會忘記關閉、善后等操作。

例如,打開文件,關閉文件的操作寫在一起:

open()defer file.Close() ... 操作文件 ...

以下是defer的一些常用場景:

打開關閉文件鎖定、釋放鎖建立連接、釋放連接作為結尾輸出結尾信息清理垃圾(如臨時文件)


panic()和recover()

panic()用于產生錯誤信息并終止當前的goroutine,一般將其看作是退出panic()所在函數(shù)以及退出調用panic()所在函數(shù)的函數(shù)。例如,G()中調用F(),F(xiàn)()中調用panic(),則F()退出,G()也退出。

注意,defer關鍵字推遲的對象是函數(shù)最后調用的,即使出現(xiàn)了panic也會調用defer推遲的對象。

例如,下面的代碼中,main()中輸出一個start main之后調用a(),它會輸出start a,然后就panic了,panic()會輸出panic: panic in a,然后報錯,終止程序。

func main() { println("start main")    a() println("end main")} func a() { println("start a") panic("panic in a") println("end a")}

執(zhí)行結果如下:

start mainstart apanic: panic in agoroutine 1 [running]:main.a()        E:/learning/err.go:14 +0x63main.main()        E:/learning/err.go:8 +0x4c exit status 2

注意上面的end a和end main都沒有被輸出。

可以使用recover()去捕獲panic()并恢復執(zhí)行。recover()用于捕捉panic()錯誤,并返回這個錯誤信息。但注意,即使recover()捕獲到了panic(),但調用含有panic()函數(shù)的函數(shù)(即上面的G()函數(shù))也會退出,所以如果recover()定義在G()中,則G()中調用F()函數(shù)之后的代碼都不會執(zhí)行(見下面的通用格式)。

以下是比較通用的panic()和recover()的格式:

func main() {    G() // 下面的代碼會執(zhí)行 ...CODE IN MAIN...} func G(){ defer func (){ if str := recover(); str != nil {            fmt.Println(str)        }    }()    ...CODE IN G()... // F()的調用必須在defer關鍵字之后 F() // 該函數(shù)內下面的代碼不會執(zhí)行 ...CODE IN G()...} func F() {    ...CODE1... panic("error found") // 下面的代碼不會執(zhí)行 ...CODE IN F()...}

可以使用recover()去捕獲panic()并恢復執(zhí)行。但以下代碼是錯誤的:

func main() { println("start main")    a() println("end main")} func a() { println("start a") panic("panic in a") // 直接放在panic后是錯誤的 panic_str := recover() println(panic_str) println("end a")}

之所以錯誤,是因為panic()一出現(xiàn)就直接退出函數(shù)a()和main()了。要想recover()真正捕獲panic(),需要將recover()放在defer的推遲對象中,且defer的定義必須在panic()發(fā)生之前。

例如,下面是通用格式的示例:

package main import "fmt" func main() { println("start main")    b() println("end main")} func a() { println("start a") panic("panic in a") println("end a")} func b() { println("start b") defer func() { if str := recover(); str != nil {            fmt.Println(str)        }    }()    a() println("end b")}

以下是輸出結果:

start main start b start apanic in a end main

注意上面的end b、end a都沒有被輸出,但是end main輸出了。

panic()是內置的函數(shù)(在包builtin中),在log包中也有一個Panic()函數(shù),它調用Print()輸出信息后,再調用panic()。go doc log Panic一看便知:

$ go doc log Panic func Panic(v ...interface{}) Panic is equivalent to Print() followed by a call to panic().

關于defer關鍵字、panic和recover的示例分析就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

網(wǎng)站名稱:defer關鍵字、panic和recover的示例分析-創(chuàng)新互聯(lián)
轉載注明:http://aaarwkj.com/article32/csoosc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供自適應網(wǎng)站、搜索引擎優(yōu)化網(wǎng)頁設計公司、定制網(wǎng)站、軟件開發(fā)、外貿網(wǎng)站建設

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設
中文字幕一区中出爽亚洲| 日本一二不卡高清在线视频 | 宫部凉花中文字幕在线| 国产一级一片内射在线| 久久精品国产亚洲熟女| 亚洲精品一区二区毛豆| 国产精品中文字幕第一页| 未满十八勿进黄网观看| 人人妻人人澡人人揉| 成人黄片在线免费播放| 黄色大全欧美在线观看| 在线日韩观看免费av| 日本激情精品在线观看| 男人天堂av网在线观看| 99久久夜国产精品| 国产精品一区二区三区久久| 青青青久热国产精品视频| 色香蕉精品国产综合| 国产产品在线免费看91| 夜夜爽精品国产亚洲av成人| 亚乱熟女一区二区三区| 亚洲超清av在线播放一区二区| 最近免费欧美一级黄片| 欧美午夜一级特黄大片| 国产成人亚洲合色婷婷 | 日韩av高清在线播放| 蜜桃av网站免费观看| 成人三级中文字幕电影| 在线观看中文字幕不卡二区| 久久精品国产一区二区| 亚洲中文字幕一区二区人妻| av天堂网站在线观看| 日韩视频看看色网站| 中文字幕在线感觉av| 精品人妻一区二区在线99| 精品久久人人做爽综合| 日韩亚洲av一区二区| 国产在线一区二区三区观看| 国产午夜福利视频合集| 尤物资源视频在线观看| 五月婷婷丁香婷婷丁香|