2013年2月12日 星期二

淺談 golang 的 panic與 recover

在討論 golang 的 panic 與recover前
先來看看 python 的例外處理機制




try:
    # block 1
    raise Exception("Exception")
except ValueError as e:
    print e
except Exception as e:
    print e

這段程式碼,
在 block 1區塊會拋出例外
當例外拋出時,就不會執行該區塊剩下的程式碼
就會開始找except語句

他會比對第一個except句子"except ValueError as e:"。
因為拋出的例外不是 ValueError 的物件或子類別物件
因此他會檢查第二敘述
第二個敘述"except Exception as e" 滿足條件
因此他會執行 "except Exception as e"  下的 block


golang 比較特殊,你可以把 golnag 的 panic/recover 想像成,他所有的 function 都被 try 把起來,而執行 catch 例外的動作則是交由 defer function 中的 recover 負責。


package main

import(
    "fmt"
)

func test(){
    defer func(){
        e := recover()
        fmt.Print(e)
        fmt.Print("\n")
    }()
    panic(1)
}

func main(){
    test()
}

不過你會發現, golang 他會 catch 各種例外。有時這不是我們想要的。解決方法有很多種,其中一個方法是建立一個 exception 結構,用結構中的欄位去區分例外。第二個方法就用 reflection。 利用欄位區分例外
package main

import(
    "fmt"
)

type Exception struct{
    Exception_type int
}

func test(){
    defer func(){
        e, ok := recover().(Exception)
        if !ok{
            fmt.Printf("Type assertions error")
        }
        switch e.Exception_type{
        case 1:
            fmt.Printf("1\n")
        default:
            fmt.Printf("Other exception\n")
        }
    }()
    var e Exception
    e.Exception_type = 1
    panic(e)
}

func main(){
    test()
}

沒有留言:

張貼留言