defer是什麼?
在Go語言中,可以使用關鍵字defer向函數註冊退出調用,即主函數退出時,defer後的函數才被調用。defer語句的作用是不管程序是否出現異常,均在函數退出時自動執行相關代碼。
defer的用途
在函數中,程序員經常需要創建資源(比如:數據庫連接、文件句柄、鎖等) ,爲了在函數執行完 畢後,及時的釋放資源,Go 的設計者提供 defer (延時機制)。
package main import "fmt" //defer 可以向函數註冊、退出調用,即當主調函數退出時,defer後的函數才被調用, // defer語句的作用就是不管程序是否出現異常,均在函數退出是自動執行相關代碼 func sum(n1 int,n2 int) int{ //當執行到defer時,暫時不執行,會將defer後面的語句壓入到獨立的(defer棧) //當函數執行完畢後,再從defer棧 安裝先入後出的方式出棧執行 //defer 將語句放入到棧時,也會將相關的值拷貝同時入棧*** defer fmt.Println("ok1 n1=",n1)//defer3 ok3 n1 20 defer fmt.Println("ok2 n2=",n2) //defer2 ok2 n2 10 //n1 ++ //n2 ++ res := n1 + n2 fmt.Println("ok3 res=",res)//1.ok1 return res } func main() { res :=sum(20,10) fmt.Println("res=",res) }
執行結果
結果分析:
從執行結果來看,res=30 是最先開始執行的部分,接下來是第二個defer n2爲10 最後執行的是第一個defer n1爲20 ,即當執行到defer時,暫時不執行,會將defer後面的語句壓入到獨立的(defer棧),當函數執行完畢後,再從defer棧,按照(先入後出)的方式出棧執行。
注意事項:
1) 當 go 執行到一個 defer 時,不會立即執行 defer 後的語句,而是將 defer 後的語句壓入到一個棧 中[我爲了講課方便,暫時稱該棧爲 defer 棧], 然後繼續執行函數下一個語句。
2) 當函數執行完畢後,在從 defer 棧中,依次從棧頂取出語句執行(注:遵守棧 先入後出的機制),
3) 在 defer 將語句放入到棧時,也會將相關的值拷貝同時入棧
package main import "fmt" //defer 可以向函數註冊、退出調用,即當主調函數退出時,defer後的函數才被調用, // defer語句的作用就是不管程序是否出現異常,均在函數退出是自動執行相關代碼 func sum(n1 int,n2 int) int{ //當執行到defer時,暫時不執行,會將defer後面的語句壓入到獨立的(defer棧) //當函數執行完畢後,再從defer棧 安裝先入後出的方式出棧執行 //defer 將語句放入到棧時,也會將相關的值拷貝同時入棧*** defer fmt.Println("ok1 n1=",n1)//defer3 ok3 n1 20 defer fmt.Println("ok2 n2=",n2) //defer2 ok2 n2 10 n1 ++ n2 ++ res := n1 + n2 fmt.Println("ok3 res=",res)//1.ok1 return res } func main() { res :=sum(20,10) fmt.Println("res=",res) }
執行結果:
從結果看出n1++ ,n2++兩個的值未入相關defer的棧,即defer 將語句放入到棧時,也會將相關的值拷貝同時入棧。