从恐慌中恢复过来

一个常见的错误是声明一个切片并开始从中请求索引而不进行初始化,这会导致索引超出范围的恐慌。以下代码解释了如何在不退出程序的情况下从恐慌中恢复,这是恐慌的正常行为。在大多数情况下,以这种方式返回错误而不是在恐慌中退出程序仅对开发或测试目的有用。

type Foo struct {
    Is []int
}

func main() {
    fp := &Foo{}
    if err := fp.Panic(); err != nil {
        fmt.Printf("Error: %v", err)
    } 
    fmt.Println("ok")
}

func (fp *Foo) Panic() (err error) {
    defer PanicRecovery(&err)
    fp.Is[0] = 5
    return nil
}

func PanicRecovery(err *error) {

    if r := recover(); r != nil {
        if _, ok := r.(runtime.Error); ok {
             //fmt.Println("Panicing")
             //panic(r)
             *err = r.(error) 
        } else {
            *err = r.(error)
        }
    }
}

使用单独的函数(而不是闭包)允许在易于恐慌的其他函数中重用相同的函数。