要怎麼減少犯錯的機會呢?盡量減少fopen和fclose之間的距離,越近越好。最好是fopen完就呼叫fclose,這樣犯錯的可能性就降低很多了。
可是你fopen後馬上fclose,這樣好像也沒有意義。所以怎麼辦呢? go 語言引進了一個機制,類似物件的解構子,只是他是適用於 function。 當一個 function 的敘述是defer 開頭的,他不會立刻執行,他會等到函數結束時才會執行。
來看個簡單的例子。
package main import "fmt" func test(){ fmt.Printf("test start\n") for i := 0; i < 5; i++ { defer fmt.Printf("%d\n", i) } fmt.Printf("test end\n") } func main(){ test() }
test start test end 4 3 2 1 0
你會發現,它是在印完 "test end" 後,才開始印數字。而導致這個結果都主因就是defer這個關鍵字。
defer 的作用是把後面接的指令 push 到 stack裡,等到 function執行完畢要返回到caller(在執行完return後)時,在從 stack 取出指令來執行。因為1是最先被push進去的,所以他最後被執行。
有了 defer 敘述,我們就可以這樣寫開檔指令
f, err := os.Open("somefile", os.O_RDWR | os.O_CREATE, 0666) if err != nil { return } defer f.Close()開檔案和關檔案的敘述靠的夠近,這樣就不怕忘記了!!
當然,defer 在 go lang 裡另外一個作用就是和 panic 、 recover函數搭配,改天再寫這個。
這個 blog 也有介紹 defer 、panic、recover的用法
http://blog.golang.org/2010/08/defer-panic-and-recover.html
那個 blog 有個有趣的 defer 例子,程式碼如下。
func c() (i int) { defer func() { i++ }() return 1 }
上面那段程式碼 c 的回傳值將是2,這就是為什麼我之前強調執行 defer 敘述發上在 return 後。 至於他為什麼他會這樣設計,主要是為了panic、recover。當函數執行時發生panic時,可以在 defer 的 function 裡乎要recover,並在function修改回傳值。就像下面程式碼所示範的的,當程式有panic時,他會把 err_code 改成1。
package main import "fmt" func test(){ fmt.Printf("test start\n") for i := 0; i < 5; i++ { defer fmt.Printf("%d\n", i) } fmt.Printf("test end\n") } func test1()(err_code int){ defer func() { if r := recover(); r != nil{ err_code = 1 } }() panic("123") return 0 } func main(){ ret := test1() fmt.Printf("%d\n", ret) }
沒有留言:
張貼留言