panic信息的2种打印方式

52 阅读1分钟
package main

import (
	"flag"
	"fmt"
	"runtime"
	"runtime/debug"

	"github.com/astaxie/beego/logs"
)

func main() {
	run := ""
	flag.StringVar(&run, "run", "", "run")
	flag.Parse()
	switch run {
	case "recover1":
		recover1()
	case "recover2":
		recover2()
	default:
		fmt.Printf("-run=%v is forbidden\n", run)
	}
}

func recover1() {
	defer func() {
		if r := recover(); r != nil {
			logs.Error("panic err: %#v FullStack: %s",
				r, string(debug.Stack()))
		}
	}()
	panic("one")
}

func recover2() {
	defer func() {
		if x := recover(); x != nil {
			logs.Error("panic  err: %#v, FullStack:%v", x, FullStack())
		}
	}()
	panic("two")
}

func FullStack() string {
	var buf [2 << 11]byte
	runtime.Stack(buf[:], true)
	return string(buf[:])
}

// 两者基本没有区别

输出:

go run debug-recover/main.go -run=recover1
2022/07/15 10:47:45.756 [E]  panic err: "one" FullStack: goroutine 1 [running]:
runtime/debug.Stack(0xc000111d40, 0x68ff20, 0x73dfa0)
	/usr/local/go/src/runtime/debug/stack.go:24 +0x9f
main.recover1.func1()
	/home/dev/work/debug-recover/main.go:30 +0x5b
panic(0x68ff20, 0x73dfa0)
	/usr/local/go/src/runtime/panic.go:965 +0x1b9
main.recover1()
	/home/dev/work/debug-recover/main.go:33 +0x5b
main.main()
	/home/dev/work/debug-recover/main.go:18 +0x1ad


 $ go run debug-recover/main.go -run=recover2
2022/07/15 10:47:39.548 [E]  panic  err: "two", FullStack:goroutine 1 [running]:
main.FullStack(...)
	/home/dev/work/debug-recover/main.go:47
main.recover2.func1()
	/home/dev/work/debug-recover/main.go:39 +0x90
panic(0x68ff20, 0x73dfb0)
	/usr/local/go/src/runtime/panic.go:965 +0x1b9
main.recover2()
	/home/dev/work/debug-recover/main.go:42 +0x5b
main.main()
	/home/dev/work/debug-recover/main.go:20 +0x1a6