当你的golang程序运行的好好的,结果突然程序panic了,然后你打开程序的执行日志想找原因的时候,看到如下的错误信息,是不是自己人也panic了。不用惊慌,本系列文章带你揭开Golang stack traces的神秘面纱。
Panic: Want stack trace
goroutine 1 [running]:
main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:9 +0x64
main.main()
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:5 +0x85
goroutine 2 [runnable]:
runtime.forcegchelper()
/Users/bill/go/src/runtime/proc.go:90
runtime.goexit()
/Users/bill/go/src/runtime/asm_amd64.s:2232 +0x1
goroutine 3 [runnable]:
runtime.bgsweep()
/Users/bill/go/src/runtime/mgc0.go:82
runtime.goexit()
/Users/bill/go/src/runtime/asm_amd64.s:2232 +0x1
上面的程序错误是下面一段代码导致的,当然你可以使用 recover() 防止程序崩溃,这个请关注我其他文章有关golang panic 和 recover 的知识。
01 package main
02
03 func main() {
04 slice := make([]string, 2, 4)
05 Example(slice, "hello", 10)
06 }
07
08 func Example(slice []string, str string, i int) {
09 panic("Want stack trace")
10 }
回到上面的stack trace 信息,第一行 “Panic: Want stack trace” 清晰的指出panic的信息,对应到代码中的09行。紧接着,显示了3个goroutine以及各自的状态和其他信息,目前我们只关注本代码执行panic发生的goroutine 1。
首先,能看到goroutine 1 是处于运行状态的,紧接着显示了panic出现在“main”包的“Example”函数中,包括函数的参数,最后是panic出现的代码所在文件以及所在文件行数。下面一行则是该函数“main.Example”的调用函数的信息,依此类推,直到该goroutine入口函数“main()”。从panic发生的地方一直往上追溯到本goroutine的入口,这与栈stack的顺序是一致的。下面重点以“main.Example”函数来讲解函数的参数是什么意思。
“main.Example”函数参数是6个“0x”开头的,十六进制表示的数字,我们再来看代码08行函数签名中参数明明只有3个,这是为什么呢?其实这个就涉及到golang里的基础数据类型的知识了。
- 第一个参数是一个[]string,大家知道这个是golang里面的切片类型(slice),大家还应该知道,golang里面的切片类型实际上就是指向一个数组(array)的。实际上,切片 是由三部分组成:
1. 切片指向底层数组的指针
2.切片的长度,即切片中实际元素的个数
3.切片的容量,即底层数组的长度
- 第二个参数是一个string,string在golang里面也是一个引用类型,只是这个特性被隐藏了,一般当作基本数据类型使用。string由两部分组成:
1.string指向底层byte数组的指针
2.string的长度,即底层byte数组的长度
- 第三个参数是一个int,这是一个基础数据类型,内存存的就是变量的值