Golang多線程初識-day28-線程異常(panic)

introduction

在實際業務開發中,我們可能會創建上萬個goroutine,
當其中某個goroutine panic了,且沒有捕獲(recover)錯誤,
那麼整個程序將會崩潰。
所以,養成好習慣,
每當創建一個goroutine,請記得於函數內寫下recover


未捕獲錯誤

即使創建上萬個goroutine,只要其中一個panic
程序亦無法正常執行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
"fmt"
"time"
)

func map_operation(){
var a map[string]string
//map未初始化而panic

a["123"] = "456"
}

func RunInNoError(){
fmt.Println("I'm no Error")
}

func main(){
for i:=0;i<10000;i++{
go RunInNoError()
}
go map_operation()
time.Sleep(time.Second*10)
}

result

1
2
3
4
5
6
7
8
9
10
11
12
13
...
...
I'm no Error
I'm no Error
I'm no Error
I'm no Error
panic: assignment to entry in nil map

oroutine 10005 [running]:
main.magp_operation()
/.../main.go:12 +0x4b
created by main.main
/.../main.go:22 +0x66
  • 其中一個goroutine發生panic導致主程序全數崩潰無法正常運行

捕獲(recover)錯誤

養成好習慣,不管是在匿名函數或是函數中使用goroutine,
請務必記得,於函數開始使用defer搭配recover捕獲錯誤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import (
"fmt"
"time"
)

func map_operation(){

//於函數開始使用defer搭配recover捕獲錯誤
defer func(){
if err := recover(); err != nil {
fmt.Println("Error:",err)
}
}()
var a map[string]string
//map未初始化而panic

a["123"] = "456"
}

func RunInNoError(){
fmt.Println("I'm no Error")
}

func main(){
for i:=0;i<10000;i++{
go RunInNoError()
}
go map_operation()
time.Sleep(time.Second*10)
}

result

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
...
I'm no Error
I'm no Error
I'm no Error
I'm no Error
I'm no Error
Error: assignment to entry in nil map
I'm no Error
I'm no Error
I'm no Error
I'm no Error
I'm no Error
...
...
  • 即使其中有個goroutine發生panic仍不影響,其他業務及主程序的運行