/*1 適用於函數和方法,只能跟方法或者函數*//*2 defer語句順延強制直到函數return或者panicreturn函數不是原子級,包括寫入返回參數及函數返回,defer語句在寫入返回參數後函數返回前執行*//*3 defer語句反順序執行(棧)一般用於成對開啟、關閉、串連、中斷連線、加鎖、釋放鎖釋放資源*//*4 defer語句所在處變數入棧,只是函數結束再處理 該語句,若值傳遞則後續值改變不影響defer語句, 若地址傳遞則影響defer語句 defer函數參數在defer語句執行時初始化 defer函數調用時具體執行4.1 defer記錄函數的進入和退出,trace函數*//*5 方法為一種資料類型,方法定義後,通過賦值給具有方法的資料類型,則方法的類型與賦實值型別一致,可以執行方法操作*//*6 Each time a "defer" statement executes, the function valueand parameters to the call are evaluated as usualand saved anewbut the actual function is not invoked.anew: 重新再*//*7 defer函數調用函數傳回值與函數輸入參數按正常函數處理(複製新參數),閉包函數變數更新defer函數中變數更新,但實際函數沒有啟用。*//*8 函數返回的過程是這樣子的:先給傳回值賦值,然後調用defer運算式,最後才是返回到調用函數中。利用閉包defer函數(指標)可修改傳回值的值.*//*9 defer運算式可能會在設定函數傳回值之後,在返回到調用函數之前,修改傳回值,使最終的函數傳回值與你想象的不一致*//*10 defer+panic無panic的函數按defer正常執行: defer定義,func return/panic執行deferpanic 的函數僅執行panic之後語句不執行*///package mainimport ( "fmt" "log" "time")//定義方法type defMeth struct { err bool str string}//定義介面,介面為一種資料類型,提供操作type in interface { ini() prinOut()}func (def *defMeth) ini() { def.err = true def.str = "hei"}func (def *defMeth) prinOut() { fmt.Println("just print: ", def)}type defError struct { err error str string}func (def *defError) ini() { def.err = fmt.Errorf("this is an err: %s\n", "true") def.str = "this is a bug"}func (def *defError) prinOut() { fmt.Println("just print: ", def)}func main() { var s1 defMeth var s2 defError var def in a := 1 //defer+閉包處理, a為主函數變數,a值變化該defer函數變數會更新 defer func() { fmt.Println("close package, test the value of a:", a) }() defer fmt.Println("fmt a is: ", a) //值傳遞,defer函數入棧,變數值已賦值,只是最後執行 defer func(a int) { fmt.Println("no name func a is: ", a) }(a) //地址傳遞:傳遞的為地址,若地址處值改變則操作值改變,map傳遞的地址 defer func(a *int) { fmt.Println("no name func a address is: ", *a) }(&a) //為介面賦值變數類型及變數地址 def = &s1 //a:=1 def.ini() //defer a=2 //錯誤defer後必須是函數或者方法或者介面 def.prinOut() //fmt.Println("result", bigSlowOperation()) //介面 def = &s2 def.ini() //函數中嵌套defer改變defer執行順序,函數中defer按棧執行,該函數正常執行 def.prinOut() a++ fmt.Println(a) fmt.Println("the value of bigSlow func: ", bigSlowOperation()) //10 test defer panic deferPanic()}func bigSlowOperation() int { log.Printf("main starts %s", "\n") i := 1 //非匿名函數調用參數i已確定:1 //defer fmt.Println(i) //匿名函數可調用傳回值:2 defer func() { fmt.Println(i) }() defer trace("bigSlowOperation")() // don't forget the //extra parentheses // ...lots of work… time.Sleep(10 * time.Second) // simulate slow operation //by sleeping i++ return i}//傳回值為函數,函數需要正常入棧,//函數輸入參數及返回地址按正常函數處理,//defer trace("")()//函數為trace中封裝的匿名函數,需正常處理該函數,//的形參及返回地址func trace(msg string) func() { start := time.Now() log.Printf("enter %s", msg) return func() { log.Printf("exit %s (%s)", msg, time.Since(start)) }}//10 defer+panic: what happends after a defer func panicfunc deferPanic() { //正常執行 defer fmt.Println("the last defer panic func") defer fmt.Println("the 3st defer panic func") //panic func 僅執行panic語句 defer func() { panic("test defer panic"); fmt.Println("the func panics") }() //正常執行 defer fmt.Println("the 2st defer panic func") defer fmt.Println("the 1st defer panic func")}
75 次點擊 ∙ 1 贊