之前也有文章讲过go调用堆栈的话题,但并没有完全讲清楚,这里补充里面缺漏的几个点。

阻塞

goroutine 1 [select, 2 minutes]:
复制代码

方括号里的select表示阻塞原因,具体定义见runtime.waitReason 。 后面的时间是阻塞时间。需要注意的是这只是一个大概时间,是在gc的过程中标记的,所以如果这个goroutine不需要gc,那么永远也不会有值。

PC偏移

github.com/robfig/cron.(*Cron).run(0xc0000c44b0)cron.go:191 +0x28d
复制代码

行号后面的16进制数是什么?pc偏移。是指函数入口(cron.(*Cron).run)到调用处(也就是行号指位置)的指令位置偏差。一般很少用到,除非下面这种特殊情况:

func main() {rand.Seed(time.Now().UnixNano())_, _, _ = foo(), foo(), foo()
}func foo() int {if rand.NormFloat64() > 0 {panic("")}return 0
}//main.main()
//  main.go:10 +0x7b 或 +0x80 或 +0x85
复制代码

函数参数

函数参数是最复杂的部分,牵涉到go的很多底层实现。

输入参数,输出参数

为什么经常只有一个参数的函数堆栈里却跟着两个数呢?另一个是输出。

func main() {rand.Seed(time.Now().UnixNano())r := rand.Int() //2e78e7b163438cc2fmt.Printf("%x\n", r)foo(r)
}func foo(i int) (o int) {o = rand.Int() //36dd26e720cac1fefmt.Printf("%x\n", o)defer panic("want to panic")return
}//main.foo(2e78e7b163438cc2, 36dd26e720cac1fe)
//  main.go:21 +0xdd
复制代码
结构体展开

结构体会被展开,然后比较短的字段会被打包成一个uint。

type S struct {a intb intc intd inta1 boolb1 bytec1 boold1 byte
}func main() {foo(S{})
}func foo(s S) {panic("want to panic")noInline()
}func noInline() {fmt.Sprint()
}//main.foo(0x0, 0x0, 0x0, 0x0, 0x0)
//  main.go:67 +0x39
复制代码

但是这种打包是依赖字段顺序的。

type S struct {a inta1 boolb intb1 boolc intc1 boold intd1 bool
}func main() {foo(S{})
}func foo(s S) {panic("want to panic")noInline()
}func noInline() {fmt.Sprint()
}//main.foo(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
//  main.go:67 +0x39
复制代码
函数参数对照表

下面的表涵盖了大部分情况

函数签名 输入 堆栈输出 说明
foo(float64) 1 (0x3ff0000000000000)
foo(complex64) 1+3i (0x404000003f800000) 两个32位浮点打包为一个64位数
foo(complex128) 1+3i (0x3ff0000000000000, 0x4008000000000000)
foo(string) "中文" (0x10adc82, 0x6) (指针,字节数)
foo(interface{}) "" (0x108e520, 0x10bff30) (类型指针,值指针)
foo(interface{}) (*string)(nil) (0x108b8e0, 0x0) 值为nil,类型不为nil
foo(interface{}) nil (0x0, 0x0) 值,类型都为nil
foo([]byte) make([]byte,3,6) (0xc000070f82, 0x3, 0x6) (指针,len,cap)
foo(map[string]string) make(map[string]string) (0xc000070e48)
foo(chan struct{}) make(chan struct{}) (0xc00005e060)
foo([200]int) [200]int{} (0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...) 数组展开
foo(func()) nil (0x0)
foo(int16, uint16) 1,2 (0xc000020001) 两个16位数打包为32位数,仅低32位有效
foo(bool)bool false (0xc000070f00, 0xc00005c058) 前一个数为输入,仅低8位有效,后一个数为输出,未初始化
foo(struct {a,b int}) struct {a,b int}{} (0x0, 0x0) 结构体展开
foo(struct {a int;b bool;c int;d bool;e byte}) struct {a int;b bool;c byte;d bool;e byte}{1,true,2,false,3} (0x1, 0x1, 0x2, 0x300) d,e合并,b不合并
foo(struct {a int;b bool;c string;d bool;e byte}) struct {a int;b bool;c string;d bool;e byte}{1,true,"a",false,3} (0x1, 0x1, 0x10adb18, 0x1, 0x300) d,e合并
foo(struct {a struct{a,b byte};b bool}) struct {a struct{a,b byte};b bool}{struct{a,b byte}{3,4},true} (0xc000010403) 内嵌结构体合并
foo(struct {a struct{a int;b byte};b bool}) struct {a struct{a int;b byte};b bool}{struct {a int;b byte}{5 , 7 },false} (0x5, 0xc000072f07, 0xc00005e000) 内嵌结构体不合并

[golang]如何看懂调用堆栈相关推荐

  1. golang 打印调用堆栈

    这两天看Go的代码,呃,协程太多,无数个携程调用了一个方法,彻底看不清了,所以就想到是不是可以把调用堆栈打印出来. 查了一下,发现Go的 runtime/debug 库可以把调用堆栈打出来.下面看个例 ...

  2. 获取iOS任意线程调用堆栈(五)完整实现:BSBacktraceLogger

    转载自:https://toutiao.io/posts/aveig6/preview BSBacktraceLogger 是一个轻量级的框架,可以获取任意线程的调用栈,开源在我的 GitHub,建议 ...

  3. 我的世界服务器java出错_看懂 游戏《Minecraft》的崩溃报告 服务端/客户端

    前言 [WARNING] 本篇适用于Minecraft服务端/客户端报错的诊断分析,其他游戏除外,比如网易 [WARNING] 本篇适用于Minecraft服务端/客户端报错的诊断分析,其他游戏除外, ...

  4. 如何看懂Minecraft报错的关键信息。

    让你如何看懂Minecraft报错 前言 一些俏皮话 寻找崩溃日志 打开崩溃日志 重要的事说三遍 下载文本编辑器 开始分析 深度分析 得出结论 修复报错 解决方案 看懂更多 结束 前言 [WARNIN ...

  5. Go 语言入门三部曲(一):能看懂 Go 语言

    文章目录 三部曲 搭建环境 代码简要讲解 包 导入 导出名 标识符 关键字 和 预定义标识符 基本类型 变量与常量 变量声明 短变量声明 类型转换 常量 流程控制 for 循环 if 分支 switc ...

  6. 人工智能机器学习底层原理剖析,人造神经元,您一定能看懂,通俗解释把AI“黑话”转化为“白话文”

    按照固有思维方式,人们总以为人工智能是一个莫测高深的行业,这个行业的人都是高智商人群,无论是写文章还是和人讲话,总是讳莫如深,接着就是蹦出一些"高级"词汇,什么"神经网络 ...

  7. 初看一脸懵逼,看懂直接跪下!

    往期热门文章: 1.再见 BeanUtils!性能真拉跨! 2.被公司辞退拿了22万补偿金,原东家称回来后每月涨薪7000,只要退还22万 3.用 Dubbo 传输文件?被老板一顿揍! 4.45 个 ...

  8. 一张图看懂微服务架构路线

    目录 一张图看懂微服务架构路线 我为什么选择微服务架构? 微服务架构路线 基本思路 Docker 容器编排 Docker 容器管理 API网关 负载均衡 服务发现 事件总线 日志记录 监控和警报 分布 ...

  9. 连傻瓜都能看懂的基于代码注入的线程守护技术

    连傻瓜都能看懂的基于代码注入的线程守护技术 2010年08月31日 连傻瓜都能看懂的基于代码注入的线程守护技术 Author: 叶紫孤(CPP肥兔) (感谢冷风大哥提供技术支持) E-mail: ye ...

最新文章

  1. label之间展示间距_cob小间距led显示屏分类
  2. 势能线段树/吉司机线段树-我没有脑子
  3. 关于Oracle数据库导入数据显示中文乱码
  4. Java-压缩指针compressedOops
  5. 技术人必读:如何让自己成长为IT项目管理者
  6. L1-067 洛希极限 (10 分)
  7. VMware Workstation v14.1.3 精简特别版本
  8. 计算机毕业设计 网吧计费管理系统 网吧管理系统 网吧管理系统java 网吧上机管理系统 网吧计费系统 网吧系统 网吧收费管理系统 网咖系统 网咖管理系统 网咖计费系统 网咖收费管理系统
  9. 职称计算机word中文字处理,职称计算机Word2003中文字处理考试大纲
  10. 百度地图API获取公交路线及站点数据
  11. 蓝桥杯训练题1427: [蓝桥杯][2013年第四届真题]买不到的数目【筛选符合题目的数字。有点类似筛素数】
  12. SiT2020:抗冲击抗振动宽温振荡器,1-110MHz之间频率,SOT23-5封装
  13. 游戏纽约夜生活java汉化_纽约玩乐--夜生活开启诱惑模式
  14. 程序员的时间管理计划
  15. 使用mav命令将本地jar包导入本都Maven库
  16. 服务器空间不足的解决方法
  17. 选择 DCIM 时需要注意哪些关键问题
  18. MySQL的安装(详解)
  19. 机械臂(一)---机器臂的启动
  20. 恩施机器人编程_恩施州中小学机器人项目赛事开幕

热门文章

  1. No Javascript on this page
  2. 【Xamarin】MonoTouch - iOS 使用 UIImagePickerController 打开图片库和相机选择图片修改头像...
  3. Android笔记——Windows环境下Android Studio v1.0安装教程
  4. OC反射机制获得该类全部属性并创建数据表
  5. [转载]Dynamic Database Switching in Rails - How to do it
  6. 机器学习之决策树_CART算法
  7. pre textarea code标签区别
  8. CentOS6.5 安装python
  9. javascript : instanceof,typeof,constructor
  10. JAVA虚拟机内存分配原则 (转