曹大带我学 Go(3)—— 如何用汇编打同事的脸
你好,我是小X。
曹大最近开 Go 课程了,小X 正在和曹大学 Go。
这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go。
今天介绍几个常用的查看 Go 汇编代码、调试 Go 程序的命令和工具,既可以在平时和同事、网友抬杠时使用,还能在关键时刻打他们的脸。
比如,有同事说这段代码:
package maintype Student struct {Class int
}func main() {var a = &Student{1}println(a)
}
的执行效率要高于下面这段代码:
package maintype Student struct {Class int
}func main() {var a = Student{1}var b = &aprintln(b)
}
并且给你讲了一通道理,你好像没法辩赢他。怎么办?
直接用一行命令生成汇编代码,马上可以戳穿他,打他的脸。
go tool 生成汇编
其实很简单,有两个命令可以做到:
go tool compile -S main.go
和:
go build main.go && go tool objdump ./main
前者是编译,即将源代码编译成 .o
目标文件,并输出汇编代码。
后者是反汇编,即从可执行文件反编译成汇编,所以要先用 go build
命令编译出可执行文件。
二者不尽相同,但都能看到前面两个示例代码对应的汇编代码是一致的。同事的“谣言”不攻自破,脸都被你打疼了。
找到 runtime 源码
Go 是一门有 runtime 的语言,什么是 runtime?其实就是一段辅助程序,用户没有写的代码,runtime 替我们写了,比如 Go 调度器的代码。
我们只需要知道用 go 关键字创建 goroutine,就可以疯狂堆业务了。至于 goroutine 是怎么被调度的,根本不需要关心,这些是 runtime 调度器的工作。
那我们自己写的代码如何和 runtime 里的代码对应起来呢?
前面介绍的方法就可以做到,只需要加一个 grep
就可以。
例如,我想知道 go 关键字对应 runtime 里的哪个函数,于是写了一段测试代码:
package mainfunc main() {go func() {println(1+2)}()
}
因为 go func(){}()
那一行代码在第 4 行,所以,grep 的时候加一个条件:
go tool compile -S main.go | grep "main.go:4"// 或go build main.go && go tool objdump ./main | grep "main.go:4"
马上就能看到 go func(){}()
对应 newproc()
函数,这时再深入研究下 newproc()
函数就大概知道 goroutine 是如何被创建的。
用 dlv 调试
那有同学问了,有没有其他可以调试 Go、以及和 Go 程序互动的方法呢?其实是有的!这就是我们要介绍的 dlv 调试工具,目前它对调试 Go 程序的支持是最好的。
之前没我怎么研究它,只会一些非常简单的命令,这次学会了几个进阶的指令,威力挺大,也进一步加深了对 Go 的理解。
下面我们带着一个任务来讲解 dlv 如何使用。
我们知道,向一个 nil 的 slice append 元素,不会有任何问题。但是向一个 nil 的 map 插入新元素,马上就会报 panic。这是为什么呢?又是在哪 panic 呢?
首先写出让 map 产生 panic 的示例程序:
package mainfunc main() {var m map[int]intm[1] = 1
}
接着用 go build
命令编译生成可执行文件:
go build a.go
然后,使用 dlv 进入调试状态:
dlv exec ./a
使用 b
这个命令打断点,有三种方法:
b + 地址
b + 代码行数
b + 函数名
我们要在对 map 赋值的地方加个断点。先找到代码位置:
cat -n a.go
看到:
赋值的地方在第 5 行,加断点:
(dlv) b a.go:5
Breakpoint 1 set at 0x45e55d for main.main() ./a.go:5
执行 c
命令,直接运行到断点处:
执行 disass
命令,可以看到汇编指令:
这时使用 si
命令,执行单条指令,多次执行 si
,就会执行到 map 赋值函数 mapassign_fast64
:
这时再用单步命令 s
,就会进入判断 h 的值为 nil 的分支,然后执行 panic
函数:
至此,向 nil 的 map 赋值时,产生 panic 的代码就被我们找到了。接着,按图索骥找到对应 runtime 源码的位置,就可以进一步探索了。
除此之外,我们还可以使用 bt
命令看到调用栈:
使用 frame 1
命令可以跳转到相应位置。这里 1
对应图中的 a.go:5
,也就是我们前面打断点的地方,是不是非常酷炫。
上面这张图里我们也能清楚地看到,用户 goroutine 其实是被 goexit 函数一路调用过来的。当用户 goroutine 执行完毕后,就会回到 goexit 函数做一些收尾工作。当然,这是题外话了。
另外,用 dlv 也能干第二部分“找到 runtime 源码”活。
总结
今天系统地讲了几招通过命令和工具查看用户代码对应的 runtime 源码或者汇编代码的方法,非常实用。最后再汇总一下:
go tool compile
go tool objdump
dlv
使用这些命令和工具,可以让你在看 Go 源码的过程中事半功倍。
好了,这就是今天全部的内容了~ 我是小X,我们下期再见~
欢迎关注曹大的 TechPaper 以及码农桃花源~
曹大带我学 Go(3)—— 如何用汇编打同事的脸相关推荐
- 『曹大带我学 Go 』系列文章汇总
你好,我是小 X. 之前写了 11 篇跟着曹大学 Go 的文章,今天来汇总一下. 曹大的功力深厚,但能学到多少全看自己.第一期 Go 训练营也早就结束了,但学习还得继续.后面我也会继续发布这个系列,希 ...
- 曹大带我学 Go(8)—— 一个打点引发的事故
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 最近线上事故频发,搞得焦头烂额,但是能用上跟曹 ...
- 曹大带我学 Go(6)—— 技术之外
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 有学员私下和我说,这个课程挺打击他的自信心.我 ...
- 曹大带我学 Go(2)—— 迷惑的 goroutine 执行顺序
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 上一篇文章我们讲了 Go 调度的本质是一个生产 ...
- 曹大带我学 Go(12)—— 面向火焰图编程
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 现实中听过各种面向 XX 编程,什么面向过程编 ...
- 曹大带我学 Go(11)—— 从 map 的 extra 字段谈起
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 熟悉 map 结构体的读者应该知道,hmap ...
- 曹大带我学 Go(10)—— 如何给 Go 提性能优化的 pr
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 之前 qcrao 写了一篇<成为 Go ...
- 曹大带我学 Go(9)—— 开始积累自己的工具库
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 不知道你有没有这样的经验:看了很多计算机相关的 ...
- 曹大带我学 Go(7)—— 如何优雅地指定配置项
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 最近一个年久失修的库导致了线上事故,不得不去做 ...
- 曹大带我学 Go(5)—— 哪里来的 goexit
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 在学员群里,有同学在用 dlv 调试时看到了令 ...
最新文章
- Ubuntu更新时遇到/boot空间不足
- 【翻译】【linux设备驱动】linux地址类型
- mysql olap 工具_OLAP分析工具之Presto
- 全球及中国皮裤行业消费需求及未来产销前景预测报告2022-2027年
- 使用CNN进行情感分类
- “我,程序员,33岁,距离退休,只剩2年了!”
- 001mongodb数据库介绍002mongodb的增删改查003数据导入导出
- 软件工作相关考试001---PMP等各种考试
- mysql做时间判断_mysql关于时间函数的判断
- 猿大师播放器网页播放海康威视RTSP流闪退,用新版VLC播放器播放也闪退,但是用某个老版本VLC播放器却没问题,该怎么办?
- ERPS(Ethernet Ring Protection Switching):以太网多环保护技术
- 交换机芯片技术知多少
- PDF文件转MOBI怎么转?在线操作轻松完成
- 八种抽样技术的科学指南
- js之Symbol类型
- HTML+CSS+JS雷霆战机
- 【嵌入式软件开发】之面试常识(一)
- 影集制作php源码_最新仿720全景在线制作云平台网站PHP源码
- C++ function关键字
- linux环境安装部署RF+Jenkins+Git(非完整版)
热门文章
- 高效办公!Python 批量生成PDF文档
- 10_放置街灯(Placing Lampposts,UVa 10859)
- 【必读推荐】程序员的职业素养
- 我是个28岁的IT,我现在慌得一比
- 关于 网易云音乐 我喜欢的音乐 排序无法改为添加时间 排序无法还原 的问题
- pytorch锁死在dataloader(训练时卡死)
- python 正态分布图_用python制作正态分布图
- 学计算机编程我有什么好处,学习计算机编程对我们都有什么好处?
- 搜索引擎的目标是什么?
- 用python处理excel数据做函数_如何使用python通过函数式编程完成excel中的数据处理及分析工作...