最近部门线上有一起panic导致的事故,基本都是犯的编程中的一些低级错误;引以为戒,总结了下Go里面常见的一些异常捕获以及哪一些异常不能捕获
能Recover的异常
下面几种情况是能 Recover 住的
切片或者数组下标越界
func main() {
go func() {
if err := recover(); err != nil {
fmt.Println("err:", err)
}
}()
nums := []int{}
fmt.Println(nums[1])
}
空指针异常
func main() {
var str *string
fmt.Println(*str)
}
未初始化的map进行写
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println("err:", err)
}
}()
var mp map[string]int
mp[""] = 1
}
重复关闭channel或者channle已关闭还继续写入数据
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println("err:", err)
}
}()
stopCh := make(chan struct{})
close(stopCh)
close(stopCh) // 这里会panic
stopCh <- struct{}{} // 这里也会panic
}
类型断言
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println("panic")
}
}()
var str interface{} = "123"
_ = str.(int) // 不要使用这种类型断言
}
不能Recover住的异常
下面几种情况是不能 Recover 住的
内存溢出
func main() {
_ = make([]int64, 1<<40)
fmt.Println("cover")
}
Map 并发读写
func main() {
m := map[string]int{}
go func() {
for {
m["x"] = 1
}
}()
for {
_ = m["y"]
}
}
栈内存耗尽
func main() {
var fun func([1000]int64)
fun = func(i [1000]int64) {
fun(i)
}
fun([1000]int64{})
}
报错 runtime: goroutine stack exceeds 1000000000-byte limit
将 Nil 函数交给 goroutine 启动
func main() {
var f func()
go f()
}
报错 fatal error: go of nil func value
程序死锁
func main() {
go func() {
for true {
fmt.Println("alive")
time.Sleep(time.Second * 1)
select {}
}
}()
<-make(chan int)
}