9.8Go之函数之宕机(panic)

9.8Go之函数之宕机(panic)

宕机的概念

宕机是Go语言再运行期检查出的异常(不是在编译期)--->如数组访问越界、空指针引用等

当宕机发生时:

  • 程序会中断运行,并立即执行在该 goroutine(可以先理解成线程)中被延迟的函数(defer 机制)

  • 程序崩溃、输出日志信息(panic value和函数调用的堆栈跟踪信息)

  • Go语言程序在宕机时,会将堆栈和 goroutine 信息输出到控制台

panic的应用场景:

  • panic 一般用于严重错误

  • 大部分漏洞应使用Go语言提供的错误机制而非panic

发生宕机的几种情况

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

  • 手动触发宕机


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

regexp 是Go语言的正则表达式包,正则表达式具有以下一些特点:

  • 正则表达式需要编译后才能使用

  • 编译需要必须成功

编译正则表达式的两种函数:

func Compile(expr string) (*Regexp, error) //这是位于regexp包下的一个函数
/*
发生错误时返回编译错误同时返回 Regexp 为 nil
适用于在编译错误时获得编译错误进行处理,同时继续后续执行的环境
*/
func MustCompile(str string) *Regexp
/*
编译正则表达式发生错误时,使用 panic 触发宕机
适用于直接使用正则表达式而无须处理正则表达式错误的情况
*/

MustCompile函数示例代码:

package main

import (
"fmt"
"regexp"
"strconv"
)

/*
Go语言中编译正则表达式使用的是regexp包下的函数:
1、Compile
2、MustCompile
*/
func MustCompile(str string) *regexp.Regexp {
//将形参传入正则包下的方法进行转换
regexp, error := regexp.Compile(str)
   /*
   Compile() 是编译正则表达式的入口函数,该函数返回编译好的正则表达式对象和错误
   */
if error != nil {
//手动宕机
panic(`regexp: Compile(` + strconv.Quote(str) + `): ` + error.Error())
}
//error为空,返回正则对象
return regexp
}

func main() {
fmt.Println(MustCompile("JunkingBoy"))
}

手动触发宕机

使用内建函数panic()即可触发宕机

示例代码:

package main

func main() {
//直接使用内建函数panic()手动触发宕机
panic("crash")
}

源码中的panic()函数的形参是一个interface{}

func panic(v interface{})

宕机时触发延迟执行语句

在上篇说到defer关键字的用法,在程序发生宕机的时候有以下几个特点:

  • panic() 后面的代码将不会被运行

  • panic() 函数前面已经运行过的 defer 语句会在宕机发生时发生作用

package main

import "fmt"

func main() {
defer fmt.Println("宕机后发生的事情1")
defer fmt.Println("宕机后发生的事情2")

//手动触发宕机
panic("宕机")

fmt.Println("事情3")
}

代码分析:

  • 发生宕机时panic函数之前声明的内容即便是用defer关键字修饰也会执行

  • 执行顺序按照defer关键字的规则发生

  • panic后面的内容不会被执行

章节小结:

  • 发生宕机可以是因为依赖必备资源缺失触发的,结合regexp包下的方法进行了示例

  • 手动触发宕机可以直接使程序终止运行

  • 宕机前,defer 语句会被优先执行,执行规则按照defer的规则来运行

  • 如果任何错误都使用宕机处理,也不是一种良好的设计习惯,因此应根据需要来决定是否使用宕机进行报错

posted @ 2021-09-08 19:40  俊king  阅读(466)  评论(0编辑  收藏  举报