can it recover from concurrent map writes panic?

271 阅读1分钟

not all panics can be recovered, such as map concurrent panic can not be recovered using defer-recover mechanism.

package main

import (
	"fmt"
	"strconv"
	"time"
)


func main() {
	m := map[string]int{
		"k1": 1,
		"k2": 2,
	}

	go func() {
		defer func() {
			if e := recover(); e != nil {
				fmt.Println("1", e)
			}
		}()

		for i := 3; i < 20; i++ {
			m["k"+strconv.Itoa(i)] = i
		}
	}()

	go func() {
		defer func() {
			if e := recover(); e != nil {
				fmt.Println("2", e)
			}
		}()

		for i := 3; i < 20; i++ {
			m["k"+strconv.Itoa(i)] = i
		}
	}()

	time.Sleep(1 * time.Second)
}

and also note that the code above will not panic 100%, relying on if the two goroutines are scheduling at the same time or scheduling sequentially. so the output may like:

wangfeng@wangfengdeMacBook-Pro goproject % go run src/main.go 
wangfeng@wangfengdeMacBook-Pro goproject % go run src/main.go
wangfeng@wangfengdeMacBook-Pro goproject % go run src/main.go
wangfeng@wangfengdeMacBook-Pro goproject % go run src/main.go
wangfeng@wangfengdeMacBook-Pro goproject % go run src/main.go
fatal error: concurrent map writes

goroutine 19 [running]:
runtime.throw({0x100e538a1?, 0x0?})
        /usr/local/go/src/runtime/panic.go:992 +0x50 fp=0x14000049700 sp=0x140000496d0 pc=0x100df6b90