Golang-Defer

2021-03-06 積跬Coder
defer觸發時機

A 「defer」 statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.

Go官方文檔中對defer的執行時機做了闡述,分別是。

包裹defer的函數返回時

包裹defer的函數執行到末尾時

所在的goroutine發生panic時

defer執行順序

當一個方法中有多個defer時, defer會將要延遲執行的方法「壓棧」,當defer被觸發時,將所有「壓棧」的方法「出棧」並執行。所以defer的執行順序是LIFO的。

執行順序如下

# 常規執行語句1 -> 語句2 -> 語句3 -> 語句4# 在語句2,語句3中添加defer後執行順序如下語句1 -> 語句4 -> 語句3(帶defer) -> 語句2(帶defer)

defer示例

package mainimport "fmt"func main() {
d()
}func d() {
fmt.Print("start" + " ")
fmt.Print("processing1" + " ")
fmt.Print("processing2" + " ")
fmt.Print("end" + " ")
}

沒有defer:

start  -> processing1  ->  processing2  -> end

processing1、processing2 加入defer:

start  -> end  -> processing2  -> processing1

defer使用規則defer會實時解析參數

package mainimport "fmt"func main() {
i := 0
defer fmt.Println(i)
i ++ return}// 0

這是因為雖然我們在defer後面定義的是一個帶變量的函數: fmt.Println(i). 但這個變量(i)在defer被聲明的時候,就已經確定其確定的值了

defer的類棧執行

棧:先入後出

package mainimport "fmt"func f1() {
fmt.Println(1)
}func f2() {
fmt.Println(2)
}func main() { defer f1()
f2()
}// 2\1

defer可以讀取有名返回值

func c() (i int) { defer func() { i++ }() return 1}func main() {
fmt.Println(c())
}// 2

在開頭的時候,我們說過defer是在return調用之後才執行的。這裡需要明確的是defer代碼塊的作用域仍然在函數之內,結合上面的函數也就是說,defer的作用域仍然在c函數之內。因此defer仍然可以讀取c函數內的變量(如果無法讀取函數內變量,那又如何進行變量清除呢…)。
當執行return 1 之後,i的值就是1. 此時此刻,defer代碼塊開始執行,對i進行自增操作。因此輸出2.

窮、優秀、攢錢

相關焦點

  • 聊聊golang的defer
    序本文主要研究一下golang的deferdeferreturn先賦值(對於命名返回值),然後執行defer,最後函數返回
  • golang中defer的執行過程詳解
    (給Go開發大全加星標)來源:XITEHIPhttps://www.jianshu.com/p/23402fa5f5ba【導讀】golang
  • Go 經典入門系列 28:Defer
    什麼是 defer? defer 語句的用途是:含有 defer 語句的函數,會在該函數將要返回之前,調用另一個函數。這個定義可能看起來很複雜,我們通過一個示例就很容易明白了。]在 playground 上運行: https://play.golang.org/p/IlccOsuSUE[3]切片: https://studygolang.com/articles/12121[4]函數: https://studygolang.com/articles/11892[5]方法: https://studygolang.com/articles
  • golang的defer使用相關
    ()) fmt.Println("-") deferFunc3() fmt.Println("-") deferFunc4()}func deferFunc1() { i := 1 defer fmt.Print(i) i = 2 return}func deferFunc2() (result int) { i := 1 defer func() { result
  • Golang之defer進階
    fmt.Printf("in defer: x = %d\n", x) x = 7 return 9}func test2() (x int) { x = 7 defer fmt.Printf("in defer: x = %d\n", x) return 9}func test3() (x int) { defer func() { fmt.Printf("in
  • Golang入門教程——基本操作篇
    defergolang的函數當中有一個特殊的用法,就是defer。這個用法據說其他語言也有,但是我暫時沒有見到過。defer是一個關鍵字,用它修飾的語句會被存入棧中,直到函數退出的時候執行。比如:func main() { defer fmt.Println("world") fmt.Println("hello")}上面這兩行代碼雖然defer的那一行在先,但是並不會被先執行,而是等main函數執行退出之前才會執行。
  • Golang中defer的實現原理
    前言在Go語言中,可以使用關鍵字defer向函數註冊退出調用,即主函數退出時,defer後的函數才被調用。defer語句的作用是不管程序是否出現異常,均在函數退出時自動執行相關代碼。:定義defer類似於入棧操作,執行defer類似於出棧操作,先進後出3.defer可操作主函數返回值defer語句中的函數會在return語句更新返回值後在執行。
  • go 學習筆記之解讀什麼是defer延遲函數
    無 defer 的文件拷貝有 defer 的文件拷貝上述示例代碼簡單展示了 defer 關鍵字的基本使用方式,顯著的好處在於 Open/Close 是一對操作,不會因為寫到最後而忘記 Close 操作,而且連續依賴時也能正常保證延遲時機
  • Golang中的Defer必掌握的7知識點
    本文整理的defer的全場景使用情況,部分場景源自網絡,加上自己的額外觀點和分析,完成了這份defer的7個隱性必備知識點。一個函數中,寫在前面的defer會比寫在後面的defer調用的晚。,defer後的語句後執行該知識點不屬於defer本身,但是調用的場景卻與defer有聯繫,所以也算是defer必備了解的知識點之一。
  • Golang 之輕鬆化解 defer 的溫柔陷阱
    = nil {defer f.Close()}在打開文件的語句附近,用defer語句關閉文件。這樣,在函數結束之前,會自動執行defer後面的語句來關閉文件。當然,defer會有小小地延遲,對時間要求特別特別特別高的程序,可以避免使用它,其他一般忽略它帶來的延遲。defer進階defer的底層原理是什麼?
  • Go 語言之 defer 的前世今生 - CSDN
    Jan 27, 2009. https://github.com/golang/go/commit/4a903e0b32be5a590880ceb7379e68790602c29d[Thompson, 2009] Ken Thompson. defer.
  • Go 語言之 defer 的前世今生
    /golang")6    }()7  }8}因而 defer 並不是免費的午餐,在一個複雜的調用中,當無法直接確定需要的產生的延遲調用的數量時,延遲語句將導致運行性能的下降。Jan 27, 2009. https://github.com/golang/go/commit/4a903e0b32be5a590880ceb7379e68790602c29d[Thompson, 2009] Ken Thompson. defer.
  • 深入剖析 defer 原理篇 —— 函數調用的原理?
    地址空間函數棧幀棧幀的劃定函數調用函數返回舉個例子總結本篇文章是深入剖析 golang 的 defer 的基礎知識準備,如果要完全理解 defer ,避免踩坑,這個章節的基礎知識必不可少在 golang 的一個函數的代碼裡,開頭會先保存 rbp 寄存器的值,保存到棧上,函數執行完之後,需要返回 caller 函數之前,需要恢復 rbp 寄存器。
  • 5 年 Gopher 都不知道的 defer 細節,你別再掉進坑裡!
    什麼是 deferdefer 是 Go 語言提供的一種用於註冊延遲調用的機制,每一次 defer 都會把函數壓入棧中,當前函數返回前再把延遲函數取出並執行。defer 語句並不會馬上執行,而是會進入一個棧,函數 return 前,會按先進後出(FILO)的順序執行。也就是說最先被定義的 defer 語句最後執行。
  • gRPC 實操指南(golang)
    (此處需要加入環境變量,各個系統操作不同,不贅述,protoc命令能夠正常使用即可)3.1.3 安裝golang編譯插件我們需要.proto最終生成可用的golang代碼,因而需要獨立安裝golang grpc的插件go get -u github.com/golang/protobuf/protoc-gen-go
  • golang下文件鎖的使用
    前言題目是golang下文件鎖的使用,但本文的目的其實是通過golang下的文件鎖的使用方法,來一窺文件鎖背後的機制。
  • golang之context使用
    背景golang中並發編程的三種實現方式:chan管道、waitGroup和Context。本篇將重點介紹context的使用,告訴大家基本的使用方式,做到會用。Context概念介紹context譯為上下文,golang在1.6.2的時候還沒有自己的context,在1.7的版本中就把golang.org/x/net/context包被加入到了官方的庫中。golang 的 Context包,是專門用來處理多個goroutine之間與請求域的數據、取消信號、截止時間等相關操作。
  • golang中Context的使用場景
    golang中Context的使用場景context在Go1.7之後就進入標準庫中了。它主要的用處如果用一句話來說,是在於控制goroutine的生命周期。當一個計算任務被goroutine承接了之後,由於某種原因(超時,或者強制退出)我們希望中止這個goroutine的計算任務,那麼就用得到這個Context了。
  • 使用 Panic、Defer 和 Recover 處理 Go 錯誤
    via:https://medium.com/technofunnel/error-handling-in-golang-with-panic-defer-and-recover-d77db7ae3875作者:Mayank Gupta四哥水平有限,如有翻譯或理解錯誤,煩請幫忙指出,感謝!文章源自 Medium,點讚超過 700+。
  • Go技術日報(2021-02-16)——解密 defer 原理,究竟背著程序猿做了多少事情?
    go 中文網每日資訊--2021-02-16 一、#公眾號:Go 語言中文網1.Go 語言標準庫中 atomic.Value 的前世今生2.解密 defer 原理,究竟背著程序猿做了多少事情?3.搭一個 K8s 集群二、#公眾號:亞軍進化史1.Go 技術日報(2021-02-15)——Rust 的第一印象三、#公眾號:Go 招聘1.golang