1、defer執行時機
for i:=1;i<10;i++{
defer log.Println(i)
}
上面那段簡單的代碼基本就可以說明多個defer時的執行順序了
當代碼中出現defer時,會將defer要執行的函式壓人堆疊,然后等函式執行完畢再執行defer堆疊中的內容
go1.13以前用堆分配,加入到鏈表中,再尾遞回呼叫,go1.13在堆疊上分配,如果defer過多則還是會在堆上用鏈表來管理
go1.14則做了進一步優化,defer的開銷基本很小了,
2、defer的估值時刻
defer的賦值操作并不是延遲賦值的,還是按照陳述句順序賦值的
如下:
//defer初始化值和位置有關 推遲執行的僅僅是函式體
func f3(j int) (i int) {
defer func(a int) {
i += a
log.Println("------------",j) //退出階段j=100 進入階段j=10 a=10
}(j)
j =100 //defer初始化值和位置有關
return
}
如果我們如下呼叫
f3(10)
則a的值為10,而列印的j最后會被列印100
defer分為進入階段和退出階段
在看下面的例子
func f4(j int) (i int) {
j =100 //defer初始化值和位置有關
defer func(a int) {
i += a
}(j)
return
}
a=100
3、防止defer記憶體泄漏
下面這段代碼會嚴重占用記憶體堆疊,造成短暫記憶體泄漏,有大量的檔案句柄沒有被釋放
//記憶體泄漏
func writeManyFiles(files []os.File) error {
for _, file := range files {
defer file.Close()
}
return nil
}
用函式包裹之后每回圈一個就關閉一個檔案句柄
//防止記憶體泄漏
func writeManyFiles(files []os.File) error {
for _, file := range files {
if err:= func() error {
f, err := os.Open(file)
defer f.Close()
if err != nil {
return err
}else {
return nil
}
}();err!=nil{
return err
}
}
return nil
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/36324.html
標籤:Go
上一篇:golang jwt-go的使用
