美文网首页
Go语言中的宕机panic-程序终止运行

Go语言中的宕机panic-程序终止运行

作者: 码二哥 | 来源:发表于2020-02-08 09:53 被阅读0次

参考:
http://c.biancheng.net/view/63.html

关键点

希望通过下面的关键词,能够实现目的:能够快速回忆理解复习 知识点:

1、宕机panic, 会造成程序崩溃

2、defer先执行 还是 panic先执行?

  • panic语句的defer是不执行的,

  • panic 会 触发在panic语句声明的defer语句,简单的说,就是defer先执行。

3、如何触发panic?

方式一:手动触发

方式二:运行依赖的资源缺失时,引发的宕机panic

4、panic 使用的场景?或者说,是使用panic还是error呢?

A、panic适用于严重错误时,使用的。

B、大部分场景,还是使用error比较好

5、使用宕机panic的好处

A、即使的止损,防止错误继续扩大

B、输出堆栈等信息,有利于分析错误原因

Go语言的类型系统会在编译时捕获很多错误,但有些错误只能在运行时检查,如数组访问越界、空指针引用等,这些运行时错误会引起宕机。

宕机不是一件很好的事情,可能造成体验停止、服务中断,就像没有人希望在取钱时遇到 ATM 机蓝屏一样,但是,如果在损失发生时,程序没有因为宕机而停止,那么用户将会付出更大的代价,这种代价可以是金钱、时间甚至生命,因此,宕机有时也是一种合理的止损方法。

一般而言,当宕机发生时,程序会中断运行,并立即执行在该 goroutine(可以先理解成线程)中被延迟的函数(defer 机制),随后,程序崩溃并输出日志信息,日志信息包括 panic value 和函数调用的堆栈跟踪信息,panic value 通常是某种错误信息。

对于每个 goroutine,日志信息中都会有与之相对的,发生 panic 时的函数调用堆栈跟踪信息,通常,我们不需要再次运行程序去定位问题,日志信息已经提供了足够的诊断依据,因此,在我们填写问题报告时,一般会将宕机和日志信息一并记录。

虽然Go语言的 panic 机制类似于其他语言的异常,但 panic 的适用场景有一些不同,由于 panic 会引起程序的崩溃,因此 panic 一般用于严重错误,如程序内部的逻辑不一致。任何崩溃都表明了我们的代码中可能存在漏洞,所以对于大部分漏洞,我们应该使用Go语言提供的错误机制,而不是 panic。

1、手动触发宕机

Go语言可以在程序中手动触发宕机,让程序崩溃,这样开发者可以及时地发现错误,同时减少可能的损失。

Go语言程序在宕机时,会将堆栈和 goroutine 信息输出到控制台,所以宕机也可以方便地知晓发生错误的位置,那么我们要如何触发宕机呢,示例代码如下所示:

package main
func main() {
    panic("crash")
}
代码运行崩溃并输出如下:
panic: crash

goroutine 1 [running]:
main.main()
    D:/code/main.go:4 +0x40
exit status 2

以上代码中只用了一个内建的函数 panic() 就可以造成崩溃,panic() 的声明如下:

func panic(v interface{})    //panic() 的参数可以是任意类型的。

2、在运行依赖的必备资源缺失主动触发宕机

regexp 是Go语言的正则表达式包,正则表达式需要编译后才能使用,而且编译必须是成功的,表示正则表达式可用。

编译正则表达式函数有两种,具体如下:

1) func Compile(expr string) (*Regexp, error)

编译正则表达式,发生错误时返回编译错误同时返回 Regexp 为 nil,该函数适用于在编译错误时获得编译错误进行处理,同时继续后续执行的环境。

2) func MustCompile(str string) *Regexp

当编译正则表达式发生错误时,使用 panic 触发宕机,该函数适用于直接使用正则表达式而无须处理正则表达式错误的情况。

MustCompile 的代码如下:

func MustCompile(str string) *Regexp {
    regexp, error := Compile(str)
    if error != nil {
        panic(`regexp: Compile(` + quote(str) + `): ` + error.Error())
    }
    return regexp
}

代码说明如下:

  • 第 1 行,编译正则表达式函数入口,输入包含正则表达式的字符串,返回正则表达式对象。
  • 第 2 行,Compile() 是编译正则表达式的入口函数,该函数返回编译好的正则表达式对象和错误。
  • 第 3 和第 4 行判断如果有错,则使用 panic() 触发宕机。
  • 第 6 行,没有错误时返回正则表达式对象。

手动宕机进行报错的方式不是一种偷懒的方式,反而能迅速报错,终止程序继续运行,防止更大的错误产生,不过,如果任何错误都使用宕机处理,也不是一种良好的设计习惯,因此应根据需要来决定是否使用宕机进行报错。

3、在宕机触发延迟执行语句defer

当 panic() 触发的宕机发生时,panic() 后面的代码将不会被运行,但是在 panic() 函数前面已经运行过的 defer 语句依然会在宕机发生时发生作用,参考下面代码:

package main
import "fmt"
func main() {
    defer fmt.Println("宕机后要做的事情1")
    defer fmt.Println("宕机后要做的事情2")
    panic("宕机")
}

代码输出如下:

宕机后要做的事情2
宕机后要做的事情1
panic: 宕机

goroutine 1 [running]:
main.main()
    D:/code/main.go:8 +0xf8
exit status 2

对代码的说明:

第 6 行和第 7 行使用 defer 语句延迟了 2 个语句。
第 8 行发生宕机。

宕机前,defer 语句会被优先执行,由于第 7 行的 defer 后执行,因此会在宕机前,这个 defer 会优先处理,随后才是第 6 行的 defer 对应的语句,这个特性可以用来在宕机发生前进行宕机信息处理。

相关文章

  • Go语言中的宕机panic-程序终止运行

    参考:http://c.biancheng.net/view/63.html 关键点 希望通过下面的关键词,能够实...

  • Go的内存管理

    本文翻译自Memory Management in Go,介绍了Go语言中内存管理的相关概念。 所有的计算机程序语...

  • Go scheduler

    摘要 Go 语言中的一个重要功能就是 Go scheduler, 全新的调度程序使得Go运行并行代码的性能大大提高...

  • linux后台运行程序

    查看nohup &运行的程序: 终止nohup &运行的程序:

  • Python-异常处理

    文件作用:学习Python基础-抛异常(try:except:---不终止程序运行;raise-终止程序运行) #...

  • Go语言中的并发进程以及通道通信

    goroutine 在go语言中要并发几个进程很简单 定义一个函数 用go运行一下例如下面的例子,主程序main开...

  • TODO:Go语言goroutine和channel使用

    TODO:Go语言goroutine和channel使用 goroutine是Go语言中的轻量级线程实现,由Go语...

  • 10-3 信号

    三、信号 kill 命令通常用来“ 杀死 ”(终止)进程,它可以用来终止运行不正常的程序 或 拒绝终止的程序。如下...

  • 程序实体与代码块

    程序实体 Go语言中的程序实体包括变量、常量、函数、结构体和接口。 代码块 在Go语言中,代码块一般就是一个由花括...

  • goroutine 并发常见问题实践

    程序退出时运行的 goroutine 会不会被终止 测试代码: 运行结果: 结论:主程序结束时还在运行中的 gor...

网友评论

      本文标题:Go语言中的宕机panic-程序终止运行

      本文链接:https://www.haomeiwen.com/subject/rzgbxhtx.html