要怎麼減少犯錯的機會呢?盡量減少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)
}
沒有留言:
張貼留言