Golang捕获panic堆栈信息的讲解

golang当中panic的时候如果启动的goroutine比较多,刷的信息满屏都是,在终端工具上因为刷的信息太多,找不到前边的信息,因此很有必要程序自己捕获panic,并且将错误信息输出到文件当中,以便定位排查问题。

Golang捕获panic堆栈信息

func PanicTrace(kb int) []byte {
  s := []byte("/src/runtime/panic.go")
  e := []byte("\ngoroutine ")
  line := []byte("\n")
  stack := make([]byte, kb<<10) //4KB
  length := runtime.Stack(stack, true)
  start := bytes.Index(stack, s)
  stack = stack[start:length]
  start = bytes.Index(stack, line) + 1
  stack = stack[start:]
  end := bytes.LastIndex(stack, line)
  if end != -1 {
    stack = stack[:end]
  }
  end = bytes.Index(stack, e)
  if end != -1 {
    stack = stack[:end]
  }
  stack = bytes.TrimRight(stack, "\n")
  return stack
}

该函数的优点:

  • 比直接recover()捕获的panic信息更加详尽
  • 比直接放任其panic打印的堆栈信息更精准,第一行就是发生panic的代码行
  • 比直接放任其panic打印的堆栈信息更简洁,可以指定信息量(kb)

最后注意,如果是启动的多goroutine,需要在每个goroutine执行函数的时候,写上defer PanicHandler() 否则的话是捕获不到其他goroutine当中的painc信息的。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

(0)

相关推荐

  • 用go gin server来做文件上传服务

    之前已经go get安装了gin, 现在来玩下用go gin server作图片上传服务, 代码目录如下: taoge:~/test_gin$ tree . |-- public |-- template | `-- select_file.html `-- test_gin_server.go 2 directories, 2 files taoge:~/test_gin$ test_gin_server.go内容: package main import ( "fmt" "

  • 为什么Go语言把类型声明放在后面?

    关于类型,官网上有一段仔细地介绍了一下函数指针的部分,现在的设计比起 C 的语法,清晰很多. 也就是说,类型放在后面是为了更加清晰易懂.Rob Pike 曾经在 Go 官方博客解释过这个问题(查看原文:Go's Declaration Syntax),简略翻译如下(水平有限翻译的不对的地方见谅): 引言 Go语言新人常常会很疑惑为什么这门语言的声明语法(declaration syntax)会和传统的C家族语言不同.在这篇博文里,我们会进行一个比较,并做出解答. C 的语法 首先,先看看 C 的

  • go各种import的使用方法讲解

    go的各种import 最简单的: package main import "fmt" func main() { fmt.Println("hehe") // ok } 不用说. 导入的特殊用法 那么, 带一个点, 是什么意思呢? 看看: package main import . "fmt" func main() { Println("hehe") // ok } 可见, 带点后, 在调用时可以省略包名. 继续看, 下划

  • golang中range在slice和map遍历中的注意事项

    golang中range在slice和map遍历中的注意事项 package main import ( "fmt" ) func main() { slice := []int{0, 1, 2, 3} myMap := make(map[int]*int) for _,v :=range slice{ if v==1 { v=100 } } for k,v :=range slice{ fmt.Println("k:",k,"v:",v) }

  • Golang命令行进行debug调试操作

    GoLang调试工具Delve 1.先获取呗: go get -u github.com/derekparker/delve/cmd/dlv 2.编写测试代码呗: func main(){ http.HandleFunc("/test",func(writer http.ResponseWriter,req *http.Request){ //TODO }) log.Fatal(http.ListenAndServe("127.0.0.1:8080",nil)) }

  • Go语言init函数详解

    Go init函数详解 init()函数会在每个包完成初始化后自动执行,并且执行优先级比main函数高.init 函数通常被用来: 对变量进行初始化 检查/修复程序的状态 注册 运行一次计算 包的初始化 为了使用导入的包,首先必须将其初始化.初始化总是以单线程执行,并且按照包的依赖关系顺序执行.这通过Golang的运行时系统控制,如下图所示: 初始化导入的包(递归导入) 对包块中声明的变量进行计算和分配初始值 执行包中的init函数 initial.go package main import

  • 在go中使用omitempty的代码实例

    omitempty在go中的使用 直接上代码: package main import ( "encoding/json" "fmt" ) type Person struct { Name string `json:"name"` Age int `json:"age"` Addr string `json:"addr,omitempty"` } func main() { p1 := Person{ N

  • go语言匿名函数的使用

    package main import ( "fmt" "go_code/chapter02/funinit/utils" ) // 3.全局匿名函数 var( Fun1 = func(n1 int,n2 int) int { return n1 * n2 } ) // init 函数,通常在init函数中完成初始化工作 func main(){ // 1.在定义匿名函数时就直接调用,这种方式匿名函数只能调用一次 res1 := func(n1 int,n2 int

  • golang的空标识符理解

    空白符(blank identifier) 空白符的产生可能是因为go不允许变量声明了但不使用.既然不想使用,何必声明变量呢,那就将变量用空白符代替,反正空白符就是用来抛弃的. 我们有时候看到这样的golang代码: import _ "net/http/pprof" 或 for _, c := range "11234" { log.Println(c) } 或 var _ io.Reader = (* XXX)(nil) //全局变量 或 var _ = Sui

  • 使用go gin来操作cookie的讲解

    准确地说, 这个标题是有问题的, go gin只能给浏览器返回操作cookie的指令, 真正执行cookie操作的是浏览器. 但广泛地来讲, 说go gin操作cookie, 也是可以的(间接操作) 来看go gin代码: package main import ( "github.com/gin-gonic/gin" ) func main() { router := gin.Default(); router.GET("/read_cookie", func(c

随机推荐