淺談go中defer的一個隱藏功能
在開始使用Go進行編碼時,Defer是要關注的一個很重要的特性。它非常簡單:在任何函數中,給其他函數的調用加上前綴 defer以確保該函數在外部函數退出之前立即執(zhí)行,即使外部函數出現異常被中斷,該延遲函數也將運行。
但是,你還可以使用defer在任何函數開始后和結束前執(zhí)行配對的代碼。這個隱藏的功能在網上的教程和書籍中很少提到。要使用此功能,需要創(chuàng)建一個函數并使它本身返回另一個函數,返回的函數將作為真正的延遲函數。在 defer 語句調用父函數后在其上添加額外的括號來延遲執(zhí)行返回的子函數如下所示:
func main() { defer greet()() fmt.Println("Some code here...") } func greet() func() { fmt.Println("Hello!") return func() { fmt.Println("Bye!") } // this will be deferred }
輸出以下內容:
Hello!
Some code here...
Bye!
父函數返回的函數將是實際的延遲函數。父函數中的其他代碼將在函數開始時(由 defer 語句放置的位置決定)立即執(zhí)行。
這為開發(fā)者提供了什么能力?因為在函數內定義的匿名函數可以訪問完整的詞法環(huán)境(lexical environment),這意味著在函數中定義的內部函數可以引用該函數的變量。在下一個示例中看到的,參數變量在measure函數第一次執(zhí)行和其延遲執(zhí)行的子函數內都能訪問到:
func main() { example() otherExample() } func example(){ defer measure("example")() fmt.Println("Some code here") } func otherExample(){ defer measure("otherExample")() fmt.Println("Some other code here") } func measure(name string) func() { start := time.Now() fmt.Printf("Starting function %s\n", name) return func(){ fmt.Printf("Exiting function %s after %s\n", name, time.Since(start)) } }
輸出以下內容:
Starting example
Some code here
Exiting example after 0s
Starting otherExample
Some other code here
Exiting otherExample after 0s
此外函數命名的返回值也是函數內的局部變量,所以上面例子中的measure函數如果接收命名返回值作為參數的話,那么命名返回值在延遲執(zhí)行的函數中訪問到,這樣就能將measure函數改造成記錄入參和返回值的工具函數。
下面的示例是引用《go 語言程序設計》中的代碼段:
func bigSlowOperation() { defer trace("bigSlowOperation")() // don't forget the extra parentheses // ...lots of work… time.Sleep(10 * time.Second) // simulate slow operation by sleeping } func trace(msg string) func() { start := time.Now() log.Printf("enter %s", msg) return func() { log.Printf("exit %s (%s)", msg,time.Since(start)) } }
可以想象,將代碼延遲在函數的入口和出口使用是非常有用的功能,尤其是在調試代碼的時候。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
IdeaGo啟動報錯Failed to create JVM的問題解析
這篇文章主要介紹了IdeaGo啟動報錯Failed to create JVM的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11Go 庫bytes.Buffer和strings.Builder使用及性能對比
這篇文章主要為大家介紹了Go 庫bytes.Buffer和strings.Builder使用及性能對比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12