Golang——延迟调用defer
生活随笔
收集整理的這篇文章主要介紹了
Golang——延迟调用defer
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
defer用于向當前函數注冊稍后執行的函數調用。這些調用被稱作延遲調用,它們直到當前函數執行結束前才被執行,常用于資源釋放、錯誤處理等操作
func main() {f, err := os.Open("/test.txt")if err != nil {fmt.Println("os.Open err:", err)return}defer f.Close() // 僅注冊,直到main退出前才執行 }延遲調用注冊的是調用,不是函數,需提供執行所需參數。參數值在注冊時被賦值并緩存起來,如此狀態敏感,可改用指針或閉包。延遲函數返回值會被拋棄
func main() {x, y := 1, 2defer func(a int) {println("defer x, y = ", a, y) // 為閉包引用}(x) // 注冊時復制調用參數x += 100 // 對x的修改,不會影響延遲調用y += 200println(x, y) }輸出:
101 202 defer x, y = 1 202多個延遲注冊按FILO次序執行
func main() {defer println("a")defer println("b") }輸出:
b a編譯器通過在ret指令前插入指令來實現延遲調用執行,而return和panic語句都會終止 當前函數流程,弓I發延遲調用°return不是ret,它會更新返回值
func main() {println("test:", test()) }func test() (z int) {defer func() {println("defer:", z)z += 100 // 修改命名返回值}()return 100 // 實際執行次序:z = 100, call defer, ret }輸出:
defer: 100 test: 200千萬記住,延遲調用是在函數結束時才被執行。不合理的使用方式會浪費更多的資源,甚 至造成邏輯錯誤。
案例:循環處理多個日志文件,defer導致文件關閉時機延長
func main() {for i := 0; i < 10000; i++ {path := fmt.Sprintf("./log/%d.txt", i)f, err := os.Open(path)if err != nil {log.Println(err)continue}defer f.Close()// 這個關閉操作在main函數結束時才會執行,而不是當前循環。// 延長了邏輯結束時間和f生命周期,平白多消耗了內存等資源。 // 編譯器也會提醒:可能發生資源泄漏,在 'for' 循環中調用 'defer' } }應該直接調用,或重構為函數,讓循環和處理算法分離
func main() {//日志處理算法。do := func(n int) {path := fmt.Sprintf("./log/%d.txt", n)f, err := os.Open(path)if err != nil {log.Println(err)return}defer f.Close() // 該延遲調用在此匿名函數結束時執行,而非main}for i := 0; i < 10000; i++ {do(i)} }相比直接用CALL指令調用函數,延遲調用則需花費更大代價。這其中包括注冊、調用等 操作,還有額外的緩存開銷。相差幾倍的結果足以引起重視。尤其是那些性能要求高且壓力大的算法,應避免使用
總結
以上是生活随笔為你收集整理的Golang——延迟调用defer的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python3 os_Python3 标
- 下一篇: MySQL笔记创建表结构_MySQL表结