package main
import (
"fmt"
"os"
"runtime"
"sync"
"time"
)
func main() {
defer fmt.Println("defer main") // will this be called when panic?
var user = os.Getenv("USER_")
wg := sync.WaitGroup{}
wg.Add(1)
go func(wgPtr *sync.WaitGroup) {
defer func() {
fmt.Println("go defer")
wgPtr.Done()
}()
defer func() {
fmt.Println("defer here")
}()
defer func() {
fmt.Println("defer caller")
if x := recover(); x != nil {
fmt.Println("recover success.")
buf := make([]byte, 1<<16)
runtime.Stack(buf, true)
fmt.Println("buf", string(buf))
}
}()
if user == "" {
panic("should set user env.")
}
fmt.Println("after panic")
}(&wg)
wg.Wait()
time.Sleep(1 * time.Second)
fmt.Printf("get result %v\r\n", user)
}
输出结果:
dev@dev-VirtualBox test $ go run test_panic_recover.go
defer caller
recover success.
buf goroutine 6 [running]:
main.main.func1.3()
/home/dev/test/test_panic_recover.go:31 +0x154
panic(0x4a2ce0, 0x4de010)
/usr/local/go/src/runtime/panic.go:969 +0x166
main.main.func1(0xc000014070, 0x0, 0xc000014110)
/home/dev/test/test_panic_recover.go:37 +0x129
created by main.main
/home/dev/test/test_panic_recover.go:17 +0x13b
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc000014118)
/usr/local/go/src/runtime/sema.go:56 +0x42
sync.(*WaitGroup).Wait(0xc000014110)
/usr/local/go/src/sync/waitgroup.go:130 +0x64
main.main()
/home/dev/test/test_panic_recover.go:41 +0x149
defer here
go defer
get result
defer main
其中调用栈第一行的信息 /home/dev/test/test_panic_recover.go:31,其实就是runtime.Stack(buf, true)的位置,以后的信息就是panic的发生地方和调用地方等等。
有疑问加站长微信联系(非本文作者)