go 之 defer, panic 和 recover

Defer

defer用于当前一个方法或者函数的延迟执行(或者当前所创建的匿名函数),他会在外围函数或者方法返回之前执行, 如果存在多个defer的话, 它比较符合LIFO(先进后出)的顺序执行。类似于析构函数的感觉

一个常用的场景, 就是文件操作的时候

var file *os.File
var err error
if file, err = os.Open(filename); err != nil {
    log.Println("file open faild", err)
    return
}
defer os.Close() //这个值将在回收之前释放资源

来看一个实际可行的例子

func main()  {

    fmt.Println("start")

    time.Sleep(time.Second * 2)

    defer func() {fmt.Println("first")}()
    defer func() {fmt.Println("second")}()
    defer func() {fmt.Println("three")}()

    return
}

start
//两秒后, 这里就符合了LIFO的顺序
three
second
first

Panic 和 Recover

通过内置的panic和recover函数。 GO提供了一套异常处理机制。GO语言将异常和错误是区别对待的, 错误是指可能出错的东西, 程序要以优雅的方法将它处理了, 可是异常是指 "不可能"发生的事儿,例如 true 永远不可能为false。

如果你自己写入了扩展包的话, 其实不推荐使用panic的, 还是以error形式返回比较好, 除非逼不得已必须使用, 必须要让程序立即中断, 但这个时候一般就会在控制台打印出错误, 为了能够优雅的捕获panic的信息, 就必须使用recover,下面看一个简单的例子

func created(start int) int {
    if (start > 1) {
        return start
    }

    panic("wrong")
}

func lala(start int) int {
    if start > 1 {
        return start
    }

    panic("this is not right")
}
func main()  {

    defer func() {
        if e := recover(); e!=nil {
            fmt.Println(e)
        }
    }()
    fmt.Println(created(2))
    lala(1)

    fmt.Println("continue")
    return
}

2
this is not right // 输出

为了能够优雅的捕获panic错误, 这里就必须用defer和recover来进行捕获打印。但是整个程序还是会被终端的, 所以你看不到"continue"这个字符串。这里要提一点的是, defer必须放在前面, 虽然他是符合LIFO的, 但是不要忘了程序是顺序执行的。这里就做一下简单的介绍。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!