目录

一 panic机制

  panic会将这个异常不断向上抛出,直到有地方处理它,如果有处理,则不会再向上抛出。倘若没有处理,那么最终会导致main挂掉.

 golang虽然没有try catch机制,却有一种类似的recover机制,后续demo我们可以观测到它的用法和作用

二 实例   

2.1 main用recover

func main() {
    defer func() {
        if err := recover(); err != nil {
            log.println("err:", err)
        }
    }()
    go test1()
    time.sleep(time.second * 3)
    panic(errors.new("stop test1"))
    log.println("123")
    select {}
}
func test1() {
    for {
        tm := time.newticker(time.second)
        select {
        case <-tm.c:
            log.println("test1")
        }
    }
}

2.2 func用recover

func main() {
    defer func() {
        if err := recover(); err != nil {
            log.println("err:", err)
        }
    }()
    go test1()
    time.sleep(time.second * 3)
    makeerr()
    log.println("123")
    select {}
}
 
func test1() {
    for {
        tm := time.newticker(time.second)
        select {
        case <-tm.c:
            log.println("test1")
        }
    }
}
func makeerr() {
    defer func() {
        if err := recover(); err != nil {
            log.println("makeerr:", err)
        }
    }()
    panic(errors.new("stop"))
}

此时我们在func中用recover,那么挂掉的只是func,他不会抛到main中,所以main能继续运行,继而main开辟的go test1也能继续运行

2.3 func用recover且开创goroutine

func main() {
    defer func() {
        if err := recover(); err != nil {
            log.println("err:", err)
        }
    }()
 
    time.sleep(time.second * 3)
    makeerr()
    log.println("123")
    select {}
}
 
func test1() {
    for {
        tm := time.newticker(time.second)
        select {
        case <-tm.c:
            log.println("test1")
        }
    }
}
func makeerr() {
    defer func() {
        if err := recover(); err != nil {
            log.println("makeerr err:", err)
        }
    }()
    go test1()
    panic(errors.new("stop test"))
}

我们发现,func虽然挂掉了,但是他开创的go没挂掉,因为即使是这个函数退出了,新开的协程是相当于基于main下的一个子程,只要main不退出,他依然会“存活”

2.4 goroutine中panic

func main() {
    defer func() {
        if err := recover(); err != nil {
            log.println("err:", err)
        }
    }()
    go test1()
    time.sleep(time.second * 3)
    log.println("123")
    select {}
}
func test1() {
    log.println("test1 start")
    panic(errors.new("stop test1"))
    log.println("test1 end")
}

协程中如果没recover,那么error就会抛向main,main就会挂掉,从而没有执行到后面的log打印。

—> 这种情况,main中做defer recover是没用的

2.5 func1内嵌func2中panic且func2做处理

func main() {
    test1()
    time.sleep(time.second * 3)
    log.println("123")
}
func test1() {
    log.println("test1 start")
    test2()
    log.println("test1 end")
}
func test2() {
    defer func() {
        if err := recover(); err != nil {
            log.println("test2 err:", err)
        }
    }()
    log.println("test2 start")
    panic(errors.new("stop test2"))
    log.println("test2 end")
}

2.6 func1内嵌func中panic且func1做处理

func main() {
    test1()
    time.sleep(time.second * 3)
    log.println("123")
}
func test1() {
    defer func() {
        if err := recover(); err != nil {
            log.println("test? err:", err)
        }
    }()
    log.println("test1 start")
    test2()
    log.println("test1 end")
}
func test2() {
    log.println("test2 start")
    panic(errors.new("stop test2"))
    log.println("test2 end")
}

func2异常,执行终止,向调用者func1抛出进而本身退出,func1得到异常,执行终止,本身退出时recover进行处理,从而保活了main

到此这篇关于golang panic及处理机制的文章就介绍到这了,更多相关golang panic内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!