上卷 程序设计
中卷 标准库
- bufio 1.18
- bytes 1.18
- io 1.18
- container 1.18
- encoding 1.18
- crypto 1.18
- hash 1.18
- index 1.18
- sort 1.18
- context 1.18
- database 1.18
- connection
- query
- queryrow
- exec
- prepare
- transaction
- scan & null
- context
- tcp
- udp
- http
- server
- handler
- client
- h2、tls
- url
- rpc
- exec
- signal
- embed 1.18
- plugin 1.18
- reflect 1.18
- runtime 1.18
- KeepAlived
- ReadMemStats
- SetFinalizer
- Stack
- sync 1.18
- atomic
- mutex
- rwmutex
- waitgroup
- cond
- once
- map
- pool
- copycheck
- nocopy
- unsafe 1.18
- fmt 1.18
- log 1.18
- math 1.18
- time 1.18
- timer
下卷 运行时
源码剖析
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
调试
Delve 是官方扶持的源码级别调试器,能满足日常开发需要。
https://github.com/go-delve/delve ,version 1.8
详细信息请参考官方文档,本文记录一些基本操作。
- 编译并调试,使用
dlv debug
。 - 已编译程序,使用
dlv exec
。 - 已运行程序,使用
dlv attach
。 - 检查 core dump,使用
dlv core
。 - 服务器模式(deubg server)以
--headless
启动,客户端dlv connect
接入。
调试模式:
- 自动以
-gcflags all=-N -l
方式编译。 - 如向
go build
传递参数,使用--build-flags
。 - 支持
runtime.Breakpoint()
设置断点。
示例代码:
package main func add(x, y int) int { z := x + y return z } func main() { println(add(1, 2)) }
1. 位置
相关命令需要一个位置参数(linespec)。
l, ls, list
: 查看源码。
<filename>:<line>
: 源文件名和行号。<line>
: 当前源文件行号。<func>:<line>
: 函数内第几行。(定义为起点 0)
+<offset>
,-<offset>
: 基于当前行的偏移量。*<address>
: 内存地址。/regex/
: 正则表达式匹配的函数。
(dlv) b main.add:2 (dlv) c 3: func add(x, y int) int { 4: z := x + y => 5: return z 6: }
2. 断点
以下面的示例进行演示。
b, break
: 设置断点。bp, breakpoints
: 显示所有已设置断点。
toggle
: 开关断点。clear, clearall
: 删除指定或全部断点。
cond, condtion
: 设置断点命中条件。on
: 设置断点命中执行命令。t, tracepoint
: 设置跟踪点。
(dlv) b main.add:2 (dlv) bp Breakpoint 1 (enabled) at 0x45b4ef for main.add() ./main.go:5 (0) (dlv) on 1 locals (dlv) cond 1 x == 1 (dlv) bp Breakpoint 1 (enabled) at 0x45b4ef for main.add() ./main.go:5 (0) cond x == 1 locals (dlv) c > main.add() ./main.go:5 (hits goroutine(1):1 total:1) (PC: 0x45b4ef) z: 3 1: package main 2: 3: func add(x, y int) int { 4: z := x + y => 5: return z 6: }
(dlv) clear 1 Breakpoint 1 cleared at 0x45b4ef for main.add() ./main.go:5 (dlv) clearall
特殊 “断点” (tracepoint),它不会中断程序执行,仅在命中时(hit)输出信息。
可用来跟踪代码是否被执行。
(dlv) t abc main.add Tracepoint abc set at 0x45b4c0 for main.add() ./main.go:3
可在汇编指令级别设置断点。
(dlv) b *0x45b53e Breakpoint 2 set at 0x45b53e for main.main() ./main.go:9 (dlv) c > main.main() ./main.go:9 (hits goroutine(1):1 total:1) (PC: 0x45b53e)
3. 运行
调试器启动时,会在 _rt0_amd64_linux 处停住,并非 main.main 用户代码入口。
c, continue
: 继续运行,直到某个断点被命中。n, next
: 下一源码行(或指定行数)。s, step
: 下一行,进入所调用函数内部。
so, stepout
: 执行,直到跳出当前函数。si, step-instruction
: 下一条指令(汇编)。
r, restart
: 重启。rebuild
: 重新编译,重启调试。q, exit
: 退出。
不输入命令,直接回车,表示执行上一条命令。连续单行执行时,很方便。
4. 堆栈
调用堆栈(call stack)由函数栈帧(stack frame)组成。
bt, stack
: 显示整个调用堆栈。frame
: 设置缺省栈帧。up, down
: 调整缺省堆栈。
调整缺省栈帧后,bt 列表里没有相关提示。可用 list 输出源码,开头会显示栈帧编号。
(dlv) b main.add (dlv) c (dlv) bt 0 0x000000000045b4c0 in main.add at ./main.go:3 1 0x000000000045b525 in main.main at ./main.go:9 2 0x0000000000432a18 in runtime.main at src/runtime/proc.go:250 3 0x0000000000458501 in runtime.goexit at src/runtime/asm_amd64.s:1571
可在某个具体的 goroutine 上执行调试命令。
gr, goroutine
: 显示或修改默认 G。grs, goroutines
: 列出所有 G。
tr, thread
: 切换线程。threads
: 列出所有线程。
(dlv) gr Thread 13551 at ./main.go:3 Goroutine 1: Runtime: ./main.go:3 main.add (0x45b4c0) User: ./main.go:3 main.add (0x45b4c0) Go: <autogenerated>:1 runtime.newproc (0x45a9c5) Start: src/runtime/proc.go:145 runtime.main (0x432840) (dlv) grs * Goroutine 1 - User: ./main.go:3 main.add (0x45b4c0) (thread 13551) Goroutine 2 - User: proc.go:362 runtime.gopark (0x432e32) [force gc (idle)] Goroutine 3 - User: proc.go:362 runtime.gopark (0x432e32) [GC sweep wait] Goroutine 4 - User: proc.go:362 runtime.gopark (0x432e32) [GC scavenge wait] [4 goroutines] (dlv) gr 1 bt 0 0x000000000045b4c0 in main.add at ./main.go:3 1 0x000000000045b525 in main.main at ./main.go:9 2 0x0000000000432a18 in runtime.main at src/runtime/proc.go:250 3 0x0000000000458501 in runtime.goexit at src/runtime/asm_amd64.s:1571
(dlv) grs -g # 查看 goroutine 创建位置。 * Goroutine 1 - Go: <autogenerated>:1 runtime.newproc (0x45a9c5) (thread 13551) Goroutine 2 - Go: proc.go:289 runtime.init.6 (0x432ba5) [force gc (idle)] Goroutine 3 - Go: mgc.go:177 runtime.gcenable (0x414b0b) [GC sweep wait] Goroutine 4 - Go: mgc.go:178 runtime.gcenable (0x414b4a) [GC scavenge wait] [4 goroutines]
5. 查看
命中断点后,通过输出一系列相关信息来确定我们要做什么。
args
: 函数参数。locals
: 局部变量。vars
: 全局变量。whatis
: 类型信息。p, print
: 输出表达式值。display
: 每次程序中断时,输出表达式结果。set
: 修改变量值。regs
: 输出寄存器。x, examinemem
: 输出内存值。
(dlv) b main.add (dlv) c (dlv) args x = 1 y = 2 ~r0 = 4213498 # 返回值。 (dlv) set x = 100 (dlv) args x = 100 y = 2 ~r0 = 4213498
6. 测试
可以单元测试为调试入口。
调试器用
--
分隔目标程序参数,可用test.run
指定具体的目标函数。
$ dlv test -- -test.run "TestB" (dlv) funcs TestB test.TestB (dlv) b test.TestB
7. 其他
文档某些命令似乎被移除。
call
: 调用函数(实验)。disass, disassemble
: 反汇编。funcs
: 函数列表(不确定函数全名时,可查)。types
: 类型列表。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论