宕机的概念
宕机是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的规则来运行
-