首頁 >後端開發 >Golang >go語言defer的用法是什麼

go語言defer的用法是什麼

王林
王林原創
2021-01-07 15:23:134852瀏覽

go語言defer的用法:1、defer語句在函數傳回之前或函數中的return語句之後執行;2、多個defer語句的執行順序是逆序執行;3、在panic語句後的defer語句不執行。

go語言defer的用法是什麼

本文操作環境:windows10系統、GO 1.11.2、thinkpad t480電腦。

(學習影片分享:程式設計影片

用法介紹:

defer是Go語言中的延遲執行語句,用來新增函數結束時執行的程式碼,常用於釋放某些已指派的資源、關閉資料庫連線、中斷socket連線、解鎖一個加鎖的資源。 Go語言機制擔保一定會執行defer語句中的程式碼。

其它語言中也有類似的機制,例如Java、C#語言裡的finally語句,C 語言裡的析構函數(Destructor)可以起類似的作用,C 語言機制擔保在物件被銷毀前一定會執行析構函數中的程式碼。 C 中的析構函數析構的是對象,Go中的defer析構的是函數。

一、defer語句執行時機

defer語句在函數傳回之前 或 函數中 return語句(return語句可能呼叫另一個函數) 之後執行。範例程式碼:

package main
 
import (
    "fmt"
)
 
func main() {
    fmt.Println(deferReturn())
}
 
func deferReturn() (ret int) {
    defer func() {
        ret++
    }()
    return 10
}

上述程式碼列印出來的值是:11。 defer語句 匿名函數中的「ret 」 對回傳值 10 加 1 變成了 11。再來看一個defer語句出現在return語句之後的程式碼:

func returnDefer() (ret int) {
    return 0
    defer func() {
        ret++
        ret++
    }()
    return 1
}

上述returnDefer函數的回傳值是:0。原因是defer語句還沒有加入上程式碼執行到"return 0"函數就回傳了,因此defer語句就沒有執行。

二、多個defer語句的執行順序是逆序執行

當出現多條 defer 語句時以逆序執行(類似棧,即後進先出)。範例程式碼:

func deferSample() {
    for i := 0; i < 5; i++ {
        defer fmt.Printf("%d ", i)
    }
}

上述程式碼將會輸出:4 3 2 1 0

三、defer與panic

1、在panic語句後面的defer語句不會被執行

範例程式碼:

func panicDefer() {
    panic("panic")
    defer fmt.Println("defer after panic")
}

上述程式碼的輸出如下:

panic: panic
goroutine 1 [running]:
main.panicDefer()
    E:/godemo/testdefer.go:17 +0x39
main.main()
    E:/godemo/testdefer.go:13 +0x20
Process finished with exit code 2

可以看到defer 語句沒有執行。

2、在panic語句前的defer語句會被執行

範例程式碼:

func deferPanic() {
    defer fmt.Println("defer before panic")
    panic("panic")
}

上述程式碼的輸出如下:

defer before panic
panic: panic
goroutine 1 [running]:
main.deferPanic()
    E:/godemo/testdefer.go:19 +0x95
main.main()
    E:/godemo/testdefer.go:14 +0x20
Process finished with exit code 2

defer 語句輸出了內容。

Go中的panic類似其它語言中的拋出異常,panic後面的程式碼不再執行(panic語句前面的defer語句會被執行)。

四、return 的實作邏輯

1、第一步給回傳值賦值(若是有名回傳值直接賦值,匿名回傳值則先宣告再賦值) ;
2、第二步驟呼叫RET回傳指令並傳入回傳值,RET會檢查是否有defer語句,若存在就先逆序插播defer語句;
3、最後RET 攜帶回傳值退出函數。

可以看出 , return 不是原子運算,函數回傳值與 RET 回傳值不一定一致。

五、defer、 return、傳回值三者順序

defer、 return、回傳值三者的執行順序是: return 最先給回傳值賦值;接著defer 開始執行一些收尾工作;最後RET 指令攜帶返回值退出函數。

相關推薦:golang教學

以上是go語言defer的用法是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn