zoukankan      html  css  js  c++  java
  • golang panic及处理

    一 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

  • 相关阅读:
    mysql的缓冲查询和非缓冲查询
    通过中看不中用的代码分析Ioc容器,依赖注入....
    register_shutdown_function AND fastcgi_finish_request
    laravel5源码讲解整理
    ERROR! MySQL is running but PID file could not be found
    读《高性能javascript》笔记(一)
    看php手册2015-03-19版后备注
    rawurlencode / urlencode
    Zen Cart屏蔽中文语言浏览器
    WooCommerce Shortcode 简码使用方式说明
  • 原文地址:https://www.cnblogs.com/bushuwei/p/15181582.html
Copyright © 2011-2022 走看看