這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
生命不止,繼續 go go go !!!
學習golang這麼久了,還沒看到類似傳統的 try…catch…finally 這種異常捕捉方式。
但是,Go中引入的Exception處理:defer, panic, recover。
那麼今天跟大家分享一下golang中的defer。閑言少敘,看一下defer的作用:
Defer is used to ensure that a function call is performed later in a program’s execution, usually for purposes of cleanup. defer is often used where e.g. ensure and finally would be used in other languages.
defer的思想類似於C++中的解構函式,不過Go語言中“析構”的不是對象,而是函數,defer就是用來添加函數結束時執行的語句。注意這裡強調的是添加,而不是指定,因為不同於C++中的解構函式是靜態,Go中的defer是動態。
引自:http://www.cnblogs.com/ghj1976/archive/2013/02/11/2910114.html
說多無用,想來個開胃菜,看看如何使用:
package mainimport "fmt"func main() { defer goodbye() defer goodnight() fmt.Println("Hello world.")}func goodnight() { fmt.Println("GoodNight")}func goodbye() { fmt.Println("Goodbye")}
輸出:
Hello world.
GoodNight
Goodbye
看出什麼了嗎?
**defer在函數結束之前執行
多個defer的執行順序: Multiple defers are stacked last-in first-out so that the most recently deferred function is run first.**
那麼defer之前就return了呢?
package mainimport "fmt"func main() { fmt.Println("Hello world.") return defer goodbye() defer goodnight()}func goodnight() { fmt.Println("GoodNight")}func goodbye() { fmt.Println("Goodbye")}
輸出:
Hello world.
defer是在return之前執行的
defer用於關閉檔案
package mainimport "fmt"import "os"func main() { f := createFile("/tmp/defer.txt") defer closeFile(f) writeFile(f)}func createFile(p string) *os.File { fmt.Println("creating") f, err := os.Create(p) if err != nil { panic(err) } return f}func writeFile(f *os.File) { fmt.Println("writing") fmt.Fprintln(f, "data")}func closeFile(f *os.File) { fmt.Println("closing") f.Close()}
defer用於鎖
func Divide(i int) error { mu.Lock() defer mu.Unlock() if i == 0 { return errors.New("Can't divide by zero!") } val /= i return nil}
defer中的坑兒
看下面的代碼:
package mainimport ( "fmt")func main() { fmt.Println(f()) fmt.Println(f1()) fmt.Println(f2())}func f() (result int) { defer func() { result++ }() return 0}func f1() (r int) { t := 5 defer func() { t = t + 5 }() return t}func f2() (r int) { defer func(r int) { r = r + 5 }(r) return 1}
輸出:
1
5
1
要使用defer時不踩坑,最重要的一點就是要明白,return xxx這一條語句並不是一條原子指令!
函數返回的過程是這樣的:先給傳回值賦值,然後調用defer運算式,最後才是返回到調用函數中。
defer運算式可能會在設定函數傳回值之後,在返回到調用函數之前,修改傳回值,使最終的函數傳回值與你想象的不一致。
出自:https://tiancaiamao.gitbooks.io/go-internals/content/zh/03.4.html