zoukankan      html  css  js  c++  java
  • panic 捕获和 throw 崩溃

    一、go 语言 panic 报错捕获 

        使用 go 语言的同学在真实项目中应该经常出现空指针使用等 panic 报错,这类报错与 C++ 中的 try-catch 模块不同,go 语言会一直将当前 panic 一直从报错栈传至最外层的栈,所以很多 go 语言的架构都会在架构中 handler 的入口添加一串代码

    1     defer func() {
    2         if x := recover(); x != nil {
    3             // TODO fix panic
    4         }
    5     }()

         这里讲几个关键字

         defer:注册一个回调函数,在当前栈退出时,按注册入栈的顺序,从最后注册的 defer 函数开始执行,函数内部发生 panic,属于可修复型崩溃,所以 go 语言会有序的退出栈,并执行 defer 函数

         recover:捕捉 panic 异常,并打断当前的 panic,进行处理修复,保证不会让单个 handler 影响到整个程序

         上述的异常捕获方法想必熟悉 go 语言的同学基本都能了解。但下面我们了解一些 go 语言中无法崩溃和修复的 throw 崩溃

     二、go 语言 throw 奔溃 

          其实 go 语言源码中一些地方有一些 throw 调用,这个函数会打印相应的 fatal msg,并退出整个程序,因为这类报错被 go 语言认为无法动态修复的崩溃。所以这类奔溃与 panic 不同,属于无法通过 defer 和 recover 捕获的崩溃(因为无法修复),简单举两个栗子

          lock:当使用一个初始化的锁,并未加锁就在代码中就解锁,就会发生 throw 崩溃

    1 var lock sync.Mutex
    2 lock.Unlock()  // fatal: sync: unlock of unlocked mutex
    3 
    4 
    5 // from go 1.91
    6 new := atomic.AddInt32(&m.state, -mutexLocked)
    7 if (new+mutexLocked)&mutexLocked == 0 {
    8     throw("sync: unlock of unlocked mutex") // post a throw
    9 }

          map:熟悉 go 语言的开发者都知道,在 go 多携程架构使用便利的情况下,往往存在很多线程不安全的变量,map 就是其中最经典的栗子,当在并发下,在没有添加读写锁的情况下对 map 进行写、读写操作时,也会抛出 throw 崩溃

    testmap := make([int],1)
    for i := 0; i < 1000; i++ {
        go func() {
                    for true{
                        testmap[1] = 10 // fatal: sync: curcurent map writes
                    }    
        }()
    }

          需要注意的是,这类崩溃是直接 down 掉整个进程的,所以我们线上使用 go 语言进行应用开发时,一定要记得使用 supervisor 之类的进程管理工具,确保进行崩溃后先拉起来,再进行修复。否则会产生大面积机器完全宕机的情况。

          再需要注意的一点是,go 语言中一个进程往往有很多 goroutinue 在同时进行,如果发生 throw 奔溃时,整个进程都会被关掉,如果通过日志,会发现打印了无数堆栈信息的日志(所有 goroutinue 的日志),这时候千万不要在堆栈日志上下功夫了,因为打印出来的都是正常日志,只需要查看日志中的 fatal 关键字即可找出真正的问题所在。

    转自:https://www.cnblogs.com/novice-dxx/p/11938681.html

  • 相关阅读:
    JS移动端滑屏事件
    css3,background-clip/background-origin的使用场景,通俗讲解
    addEventListener和on的区别
    JavaScript 变量生命周期
    label标签跳出循环
    js替换指定字符串
    使用ECMAscript5中的forEach函数遍历数组
    截取js数组中某段值(slice)
    数组的一个强大函数splice,[增,删,改]
    删除数组值
  • 原文地址:https://www.cnblogs.com/luyucheng/p/13994035.html
Copyright © 2011-2022 走看看