Golang實(shí)現(xiàn)延遲調(diào)用的項(xiàng)目實(shí)踐
延遲調(diào)用
在Go語(yǔ)言中,延遲調(diào)用(defer)是一個(gè)非常重要的特性,它允許你安排一個(gè)函數(shù)在當(dāng)前函數(shù)執(zhí)行完畢后被執(zhí)行,無(wú)論是否發(fā)生panic。
這通常用于資源清理、文件關(guān)閉、解鎖互斥鎖等操作。
1. 延遲調(diào)用
defer
語(yǔ)句會(huì)將一個(gè)函數(shù)推遲到包含該defer
語(yǔ)句的函數(shù)即將返回時(shí)執(zhí)行。推遲執(zhí)行的函數(shù)其參數(shù)會(huì)立即求值,但函數(shù)本身會(huì)延遲到外圍函數(shù)返回前才執(zhí)行。
1.1 使用場(chǎng)景
- 資源清理:如關(guān)閉文件、網(wǎng)絡(luò)連接等。
- 解鎖互斥鎖:在訪問(wèn)共享資源后,確?;コ怄i被釋放。
- 打印調(diào)試信息:在函數(shù)結(jié)束時(shí)打印一些調(diào)試信息或日志。
1.2 示例
func DeferDemo() { num := 100 num += 200 // 延遲調(diào)用 // 但是num的值是該函數(shù)調(diào)用位置計(jì)算的 defer printMessage(num) num += 5 fmt.Println(num) } func printMessage(num int) { fmt.Println("printMessage func") fmt.Println("i am in defer: ", num) }
測(cè)試方法
func TestDeferDemo(t *testing.T) { DeferDemo() }
輸出結(jié)果
=== RUN TestDeferDemo
305
printMessage func
i am in defer: 300
--- PASS: TestDeferDemo (0.00s)
PASS
2. panic
panic
是一個(gè)內(nèi)置函數(shù),當(dāng)程序運(yùn)行時(shí)遇到無(wú)法恢復(fù)的錯(cuò)誤時(shí),可以調(diào)用panic
函數(shù)。
它會(huì)立即中斷當(dāng)前函數(shù)的執(zhí)行,并開(kāi)始逐層向上執(zhí)行已注冊(cè)的延遲調(diào)用(defer
語(yǔ)句)。
在延遲調(diào)用執(zhí)行完畢后,程序會(huì)崩潰并打印出傳遞給panic
函數(shù)的值。
2.1 使用場(chǎng)景
panic
通常用于處理嚴(yán)重的運(yùn)行時(shí)錯(cuò)誤,如數(shù)組越界、空指針引用等。
2.2 示例
func panicDemo() { divide_func := func(a, b int) int { if b == 0 { panic("divide by zero") } return a / b } defer printMessage(1) divide_func(1, 0) fmt.Println("不會(huì)被執(zhí)行") }
測(cè)試方法
func Test_panicDemo(t *testing.T) { panicDemo() }
輸出結(jié)果
=== RUN Test_panicDemo
printMessage func
i am in defer: 1
--- FAIL: Test_panicDemo (0.00s)
panic: divide by zero [recovered]
panic: divide by zerogoroutine 3 [running]:
testing.tRunner.func1.2({0x1042b9dc0, 0x1042e3860})
……
3. recover
recover
是一個(gè)內(nèi)置函數(shù),它用于從panic
中恢復(fù)。
recover
只有在延遲調(diào)用的函數(shù)中調(diào)用時(shí)才有用。
在正常的執(zhí)行流程中調(diào)用recover
會(huì)返回nil
,并且不會(huì)有任何效果。
如果在延遲調(diào)用的函數(shù)中調(diào)用了recover
,并且其所在的函數(shù)是由于panic
而正在退出,那么recover
會(huì)捕獲到傳遞給panic
的值,并且阻止程序的崩潰。此時(shí),程序會(huì)繼續(xù)執(zhí)行從panic
點(diǎn)之后的代碼(如果有的話(huà))。
3.1 使用場(chǎng)景
recover
通常用于在可能引發(fā)panic
的代碼塊周?chē)砑宇~外的錯(cuò)誤處理邏輯,以允許程序在發(fā)生嚴(yán)重錯(cuò)誤時(shí)優(yōu)雅地恢復(fù)。
3.2 示例
func recoverDemo() { divideFunc := func(a, b int) int { if b == 0 { panic("divide by zero") } return a / b } saveDivideFunc := func() (int, error) { defer func() { // 捕獲任何可能的panic if r := recover(); r != nil { fmt.Println("Recovered from panic:", r) } }() // 嘗試執(zhí)行可能引發(fā)panic的操作 result := divideFunc(10, 0) // 如果沒(méi)有panic發(fā)生,則返回結(jié)果 return result, nil } divideRes, err := saveDivideFunc() if err != nil { fmt.Println(err) } else { fmt.Println(divideRes) } }
測(cè)試方法
func Test_recoverDemo(t *testing.T) { recoverDemo() }
輸出結(jié)果
=== RUN Test_recoverDemo
Recovered from panic: divide by zero
0
--- PASS: Test_recoverDemo (0.00s)
PASS
源碼
// defer_demo.go 文件 package function_demo import "fmt" func DeferDemo() { num := 100 num += 200 // 延遲調(diào)用 // 但是num的值是該函數(shù)調(diào)用位置計(jì)算的 defer printMessage(num) num += 5 fmt.Println(num) } func printMessage(num int) { fmt.Println("printMessage func") fmt.Println("i am in defer: ", num) } func panicDemo() { divideFunc := func(a, b int) int { if b == 0 { panic("divide by zero") } return a / b } defer printMessage(1) divideFunc(1, 0) fmt.Println("不會(huì)被執(zhí)行") } func recoverDemo() { divideFunc := func(a, b int) int { if b == 0 { panic("divide by zero") } return a / b } saveDivideFunc := func() (int, error) { defer func() { // 捕獲任何可能的panic if r := recover(); r != nil { fmt.Println("Recovered from panic:", r) } }() // 嘗試執(zhí)行可能引發(fā)panic的操作 result := divideFunc(10, 0) // 如果沒(méi)有panic發(fā)生,則返回結(jié)果 return result, nil } divideRes, err := saveDivideFunc() if err != nil { fmt.Println(err) } else { fmt.Println(divideRes) } }
package function_demo import "testing" func TestDeferDemo(t *testing.T) { DeferDemo() } func Test_panicDemo(t *testing.T) { panicDemo() } func Test_recoverDemo(t *testing.T) { recoverDemo() }
到此這篇關(guān)于Golang實(shí)現(xiàn)延遲調(diào)用的項(xiàng)目實(shí)踐的文章就介紹到這了,更多相關(guān)Golang 延遲調(diào)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang?recover函數(shù)使用中的一些坑解析
這篇文章主要為大家介紹了golang?recover函數(shù)使用中的一些坑解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Golang實(shí)現(xiàn)加權(quán)輪詢(xún)負(fù)載均衡算法
加權(quán)輪詢(xún)負(fù)載均衡算法是一種常見(jiàn)的負(fù)載均衡策略,本文主要介紹了Golang實(shí)現(xiàn)加權(quán)輪詢(xún)負(fù)載均衡算法,具有一定的參考價(jià)值,感興趣的可以了解一下2024-08-08源碼解析gtoken替換jwt實(shí)現(xiàn)sso登錄
這篇文章主要為大家介紹了源碼解析gtoken替換jwt實(shí)現(xiàn)sso登錄的示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Go語(yǔ)言中使用flag包對(duì)命令行進(jìn)行參數(shù)解析的方法
這篇文章主要介紹了Go語(yǔ)言中使用flag包對(duì)命令行進(jìn)行參數(shù)解析的方法,文中舉了一個(gè)實(shí)現(xiàn)flag.Value接口來(lái)自定義flag的例子,需要的朋友可以參考下2016-04-04Golang語(yǔ)言如何讀取http.Request中body的內(nèi)容
這篇文章主要介紹了Golang語(yǔ)言如何讀取http.Request中body的內(nèi)容問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03golang中g(shù)in框架接入jwt使用token驗(yàn)證身份
本文主要介紹了golang中g(shù)in框架接入jwt使用token驗(yàn)證身份,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12Go語(yǔ)言排序算法之插入排序與生成隨機(jī)數(shù)詳解
從這篇文章開(kāi)始將帶領(lǐng)大家學(xué)習(xí)Go語(yǔ)言的經(jīng)典排序算法,比如插入排序、選擇排序、冒泡排序、希爾排序、歸并排序、堆排序和快排,二分搜索,外部排序和MapReduce等,本文將先詳細(xì)介紹插入排序,并給大家分享了go語(yǔ)言生成隨機(jī)數(shù)的方法,下面來(lái)一起看看吧。2017-11-11