這是一遍看到別人的blog,在這裡把他翻譯下,也算是加深印象。原鏈結
part
#1 defer nil 函式
如果defer乙個指標指向nil的函式,在呼叫的時候會發生panic錯誤。
example:
func
main()
錯誤panic: runtime error: invalid memory address or nil pointer dereference [signal sigse**: segmentation violation code=0x1 addr=0x0 pc=0x499122]
注意需要判斷是否defer的函式是否是nil,那句**在編譯的時候不會出現問題,但是在執行的時候會出現問題,因為只有等到main結束之後才會執行。
#2 在乙個迴圈裡面呼叫多個defer
因為defer在呼叫的時候是按照棧的順序去壓的,所以當執行的時候是會按照最後壓進去的順序開始執行。
解決的辦法有,要不就直接呼叫,要不就將defr之前的設定為乙個匿名函式,然後defer
關於在loop中定義defer,還有需要主義的地方。
就是defer裡面的使用的外面的變數時候需要注意,此時是等待當前的包裹函式執行完畢之後,才會去取這個引數值。
因為defer是定義乙個指標而已,這個指標指向乙個函式。等待函式執行完畢後去執行所有的defer函式。
#3(重要)defer包裹函式
有時候需要通過defer with closures,然後defer乙個函式,而這個函式執行後會返回乙個函式。
本意是將返回的函式作為defer的函式,結果是並不會。defer最終會只註冊了第乙個函式,不管返回的函式。
example:
type database struct
func
(db *database)
connect()
(disconnect func()
)}func
main()
defer db.
connect()
fmt.
println
("online"
)//1
}
輸出:
online
connect
解決這個問題:
可以重新定義乙個函式:
disconnect :=db.connect(
)defer disconnect(
)
乙個bad practice:
通過在db.connect()
的後面加乙個 「()」:db.connect()()
也是可以的
func()
defer db.
connect()
()....
}
上面兩個輸出結果都是
connect
online
disconnect
#4 defer 乙個方法的時候出現問題直接上例子解釋
type car struct
func
(c car)
printmodel()
func
main()
defer c.
printmodel()
c.model =
"last"
}
最後輸出
first
但是如果把接收器改為指標,而不是上面的物件
func
(c *car)
printmodel()
結果就是
last
原因?
因為 在通過乙個接收器訪問方法的時候,會將其轉換為乙個將接收器作為引數的乙個函式。關鍵在於如果是定義乙個型別的變數作為接收器,那麼傳遞引數的時候是拷貝複製乙個新物件作為引數。
但是如果是指標作為接收器的話,是通過建立乙個新的指標作為引數,但是指標指向的位址還是原來的地方。
所以,在這個地方,defer的時候是帶入的是當時的乙個物件的狀態作為引數。即使後面修改了也不會影響已經產生的函式。
mybatis foreach的疑難雜症
背景 今天寫 的時候,寫了一段sql,如下所示 select product name,product type,subscription id,product period,subscription begin,interest begin,interest end,subscription st...
go語言defer的使用
go語言的defer 延遲執行 語句,是在函式結束前執行,而如果在函式中有多個defer語句時,會像乙個堆疊一樣,先進後出,後進先出。defer語句在進行一些開啟資源的操作時,遇到錯誤需要提前返回,在返回前你需要關閉相應的資源,不然很容易造成資源洩露等問題上很試用。舉個defer語句簡單的使用如下 ...
go語言的defer語句
go語言defer語句的用法 參考 defer後面必須是函式呼叫語句,不能是其他語句,否則編譯器會出錯。package main import log func foo n int int這個例子中defer後面使用的是n 指令,不是乙個函式呼叫語句,編譯器就報錯 command line argu...