關於Go裡面defer的疑難雜症

2021-10-12 17:25:13 字數 2464 閱讀 8729

這是一遍看到別人的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...