您好,登錄后才能下訂單哦!
這篇文章主要介紹“go defer的作用是什么”,在日常操作中,相信很多人在go defer的作用是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”go defer的作用是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
很多現代的編程語言中都有 defer 關鍵字,Go 語言的 defer 會在當前函數返回前執行傳入的函數,它會經常被用于關閉文件描述符、關閉數據庫連接以及解鎖資源。
使用 defer 的最常見場景是在函數調用結束后完成一些收尾工作,例如在 defer 中回滾數據庫的事務:
func InsertObj() error {
//獲取一個數據庫session
db := db.GetDB().Begin()
defer db.Rollback()
//do someting
err := db.Insert()
if err != nil{
return err
}
return db.Commit().Error
}
在使用數據庫事務時,我們可以使用上面的代碼在創建事務后就立刻調用 Rollback
保證事務一定會回滾。哪怕事務真的執行成功了,那么調用 Commit()
之后再執行 Rollback()
也不會影響已經提交的事務。
defer
的調用時機以及多次調用
defer
時執行順序defer
使用傳值的方式傳遞參數時會進行預計算,導致不符合預期的結果func main() {
defer fmt.Println(0)
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
}
上面的代碼輸出:
3
2
1
0
那么defer
的執行順序就是先進后出
func main() {
{
defer fmt.Println("defer runs")
fmt.Println("block ends")
}
fmt.Println("main ends")
}
輸出:
block ends
main ends
defer runs
可以看出defer
不是在退出代碼塊的作用域時執行的,它只會在當前函數和方法返回之前被調用
func main() {
startedAt := time.Now()
defer fmt.Println(time.Since(startedAt))
time.Sleep(time.Second)
}
輸出:
0s
調用 defer
關鍵字會立刻拷貝函數中引用的外部參數,所以 time.Since(startedAt)
的結果不是在 main
函數退出之前計算的,而是在 defer
關鍵字調用時計算的,最終導致上述代碼輸出 0s。
那么如果要解決這個問題可以改寫代碼
func main() {
startedAt := time.Now()
defer func() { fmt.Println(time.Since(startedAt)) }()
time.Sleep(time.Second)
}
輸出:
1s
雖然調用 defer
關鍵字時也使用值傳遞,但是因為拷貝的是函數指針
捕獲異常和崩潰日志:
func process() error {
defer func() {
//防止意外之外的錯誤導致程序崩潰
if err := recover(); err != nil {
//崩潰日志的捕獲
core.LogPnc.Errorf("panic : %v", err)
core.LogPnc.Errorf("%s", string(debug.Stack()))
}
}()
//do something
err := obj.CALL(parseYML)
if err != nil {
return err
}
return nil
}
釋放鎖:
func runTask() {
//上鎖
c.lk.Lock()
//釋放鎖
defer c.lk.Unlock()
//do something
}
在函數返回之前進行業務操作
func (c *ProcessEngine) Process(ph *ProcessHook) {
defer func() {
c.lk.Lock()
//邏輯處理
c.running--
c.lk.Unlock()
}()
//do something
}
到此,關于“go defer的作用是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。