Delve是个啥
Delve is a debugger for the Go programming language. The goal of the project is to provide a simple, full featured debugging tool for Go. Delve should be easy to invoke and easy to use. Chances are if you’re using a debugger, things aren’t going your way. With that in mind, Delve should stay out of your way as much as possible.
- Go语言的调试器
- 目标:提供简单、功能齐全的Go调试工具
- 容易调用、使用
- 谁家好的代码天天需要调试呀,尽量少用
如何安装
安装latest,最新版
go install github.com/go-delve/delve/cmd/dlv@latest
如果它报这个错误,证明dlv不支持该平台
go install github.com/go-delve/delve/cmd/dlv@latest
D:\goworkspace\pkg\mod\github.com\go-delve\delve@v1.21.2\service\debugger\debugger.go:32:2: found packages native (dump_other.go) and your_windows_architecture_is_not_supported_by_delve (support_sentinel_windows.go) in D:\goworkspace\pkg\mod\github.com\go-delve\delve@v1.21.2\pkg\proc\native
如何使用
go version
go version go1.20 linux/arm64dlv version
Delve Debugger
Version: 1.21.2
Build: $Id: 98f8ab2662d926245917ade2f2bb38277315c7fc $
你说啥?不会用?我也不会
不会用就看看help吧。dlv --help
Delve is a source level debugger for Go programs.Delve enables you to interact with your program by controlling the execution of the process,
evaluating variables, and providing information of thread / goroutine state, CPU register state and more.The goal of this tool is to provide a simple yet powerful interface for debugging Go programs.Pass flags to the program you are debugging using `--`, for example:`dlv exec ./hello -- server --config conf/config.toml`Usage:dlv [command]Available Commands:attach Attach to running process and begin debugging.connect Connect to a headless debug server with a terminal client.core Examine a core dump.dap Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).debug Compile and begin debugging main package in current directory, or the package specified.exec Execute a precompiled binary, and begin a debug session.help Help about any commandtest Compile test binary and begin debugging program.trace Compile and begin tracing program.version Prints version.Additional help topics:dlv backend Help about the --backend flag.dlv log Help about logging flags.dlv redirect Help about file redirection.Use "dlv [command] --help" for more information about a command.
汇总一下
命令名 | 作用 |
---|---|
attach | Attach to running process and begin debugging (白话:跟某个进程建立联系,跟某个进程搞搞暧昧呗) |
connect | Connect to a headless debug server with a terminal client.(白话:作为一个客户端,连接到一个(无头?不可描述的)调试服务) |
core | Examine a core dump. (白话:检查核心转储) |
dap | Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP). (白话:启一个服务,让客户端连接调试) |
debug | Compile and begin debugging main package in current directory, or the package specified. (白话:编译并开始调试在当前目录的main包,或者其他给定的包) |
exec | Execute a precompiled binary, and begin a debug session. (白话:执行一个预编译好的二进制文件,并开启一个调试会话) |
help | Help about any command (它会帮你哦,别的可以不会,这个必须会) |
test | Compile test binary and begin debugging program. (编译测试二进制、并开始调试程序) |
trace | Compile and begin tracing program. (追踪模式) |
version | Prints version. (版本信息啦) |
总结一下,上述命令中,如下5个用的多一点儿:
- attach
- debug
- exec
- core
- help
其他的看看帮助命令就好
使用dlv help 子命令
可查看子命令的帮助文档哈
另外还有如下不常用的命令,暂不做介绍
Additional help topics:dlv backend Help about the --backend flag.dlv log Help about logging flags.dlv redirect Help about file redirection.
子命令的具体用法
搞一个先决条件,创建一个main.go文件,写一段简单的代码进去。
就以如下代码为例,main函数中写了一个简易版的httpServer,80端口开放,访问 “http://localhost:80/” 路径,则执行一次斐波那契数列的函数。
package mainimport "net/http"func main() {http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {fib(3)})if err := http.ListenAndServe(":80", nil); err != nil {panic(err)}
}func fib(n int) int {if n < 2 {return 1}return fib(n-1) + fib(n-2)
}
下面对调试命令进行梳理
1. attach
dlv help attach
Attach to an already running process and begin debugging it.This command will cause Delve to take control of an already running process, and
begin a new debug session. When exiting the debug session you will have the
option to let the process continue or kill it.Usage:dlv attach pid [executable] [flags]Flags:--continue Continue the debugged process on start.-h, --help help for attach--waitfor string Wait for a process with a name beginning with this prefix--waitfor-duration float Total time to wait for a process--waitfor-interval float Interval between checks of the process list, in millisecond (default 1)Global Flags:--accept-multiclient Allows a headless server to accept multiple client connections via JSON-RPC or DAP.--allow-non-terminal-interactive Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr--api-version int Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)--backend string Backend selection (see 'dlv help backend'). (default "default")--check-go-version Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)--headless Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.--init string Init file, executed by the terminal client.-l, --listen string Debugging server listen address. (default "127.0.0.1:0")--log Enable debugging server logging.--log-dest string Writes logs to the specified file or file descriptor (see 'dlv help log').--log-output string Comma separated list of components that should produce debug output (see 'dlv help log')--only-same-user Only connections from the same user that started this instance of Delve are allowed to connect. (default true)
该命令主要部分: dlv attach pid,该pid是一个Go程序的pid
-
go build ./main.go
-
生成了
main
可执行文件 -
使用
nohub ./main
或者setsid ./main
启动 main 文件,此时该文件加载进内存后对应一个进程ID。 -
这里使用
ps -ef | grep main
找到程序的pid -
使用dlv attach PID 进行调试
-
输入help 看一下帮助命令
root@Ophelia:~/test# dlv attach 1680
Type 'help' for list of commands.
(dlv) help
The following commands are available:Running the program:call ------------------------ Resumes process, injecting a function call (EXPERIMENTAL!!!)continue (alias: c) --------- Run until breakpoint or program termination.next (alias: n) ------------- Step over to next source line.rebuild --------------------- Rebuild the target executable and restarts it. It does not work if the executable was not built by delve.restart (alias: r) ---------- Restart process.step (alias: s) ------------- Single step through program.step-instruction (alias: si) Single step a single cpu instruction.stepout (alias: so) --------- Step out of the current function.Manipulating breakpoints:break (alias: b) ------- Sets a breakpoint.breakpoints (alias: bp) Print out info for active breakpoints.clear ------------------ Deletes breakpoint.clearall --------------- Deletes multiple breakpoints.condition (alias: cond) Set breakpoint condition.on --------------------- Executes a command when a breakpoint is hit.toggle ----------------- Toggles on or off a breakpoint.trace (alias: t) ------- Set tracepoint.watch ------------------ Set watchpoint.Viewing program variables and memory:args ----------------- Print function arguments.display -------------- Print value of an expression every time the program stops.examinemem (alias: x) Examine raw memory at the given address.locals --------------- Print local variables.print (alias: p) ----- Evaluate an expression.regs ----------------- Print contents of CPU registers.set ------------------ Changes the value of a variable.vars ----------------- Print package variables.whatis --------------- Prints type of an expression.Listing and switching between threads and goroutines:goroutine (alias: gr) -- Shows or changes current goroutinegoroutines (alias: grs) List program goroutines.thread (alias: tr) ----- Switch to the specified thread.threads ---------------- Print out info for every traced thread.Viewing the call stack and selecting frames:deferred --------- Executes command in the context of a deferred call.down ------------- Move the current frame down.frame ------------ Set the current frame, or execute command on a different frame.stack (alias: bt) Print stack trace.up --------------- Move the current frame up.Other commands:config --------------------- Changes configuration parameters.disassemble (alias: disass) Disassembler.dump ----------------------- Creates a core dump from the current process stateedit (alias: ed) ----------- Open where you are in $DELVE_EDITOR or $EDITORexit (alias: quit | q) ----- Exit the debugger.funcs ---------------------- Print list of functions.help (alias: h) ------------ Prints the help message.libraries ------------------ List loaded dynamic librarieslist (alias: ls | l) ------- Show source code.packages ------------------- Print list of packages.source --------------------- Executes a file containing a list of delve commandssources -------------------- Print list of source files.target --------------------- Manages child process debugging.transcript ----------------- Appends command output to a file.types ---------------------- Print list of typesType help followed by a command for full documentation.
(dlv)
可以看见子命令非常之多
如下汇总一下子命令
执行程序
序号 | 子命令 | 别名 | 描述 |
---|---|---|---|
01 | call | Resumes process, injecting a function call (EXPERIMENTAL!!!) (实验性的功能,注入一个函数调用,重新执行) | |
02 | continue | c | Run until breakpoint or program termination. (执行到断点或程序中止) |
03 | next | n | Step over to next source line. (步过下一行,下一行若是函数,则调用并返回) |
04 | rebuild | Rebuild the target executable and restarts it. It does not work if the executable was not built by delve. (重新编译目标执行文件并启动他, 若该程序不是由delve编译的,则无法执行) | |
05 | restart | r | Restart process. (重启进程) |
06 | step | s | Single step through program. (单步调试,整个程序) |
07 | step-instruction | si | Single step a single cpu instruction. (单步执行cpu指令) |
08 | stepout | os | Step out of the current function. (步出当前函数) |
操纵断点
序号 | 子命令 | 别名 | 描述 |
---|---|---|---|
01 | break | b | Sets a breakpoint. (设置一个断点) |
02 | breakpoints | bp | Print out info for active breakpoints. (打印正在使用的断点) |
03 | clear | Deletes brekpoint. (根据断点编号,删除断点) | |
04 | clearall | Deletes multiple breakpoints.(删除多个断点) | |
05 | condition | cond | Set breakpoint condition. (设置断点条件) |
06 | on | Executes a command when a breakpoint is hit. (当断点命中时候,执行一个命令) | |
07 | toggle | Toggles on or off a breakpoint. (切换断点的状态,启用或关闭) | |
08 | trace | t | Set tracepoint. (设置追踪点) |
09 | watch | Set watchpoint. (设置内存观测点,看门狗的功能) |
查看程序变量和内存
序号 | 子命令 | 别名 | 描述 |
---|---|---|---|
01 | args | Print function arguments. (打印函数参数) | |
02 | display | Print value of an expression every time the program stops. (打印表达式的值,在下一行或者下一个断点) | |
03 | examinemem | x | Examine raw memory at the given address.(检查给定地址的原始内存) |
04 | locals | Print local variables. (打印局部变量) | |
05 | p | Evaluate an expression. (计算并打印表达式结果) | |
06 | regs | Print contents of CPU registers.(打印CPU 寄存器的内容) | |
07 | set | Changes the value of a variable. (给变量设置值) | |
08 | vars | Print package variables. (打印包级别变量) | |
09 | whatis | Prints type of an expression. (打印表达式类型) |
进程、协程
序号 | 子命令 | 别名 | 描述 |
---|---|---|---|
01 | goroutine | gr | Shows or changes current goroutine. (显示或切换当前协程) |
02 | goroutines | grs | List program goroutines. (列出当前程序所有的协程) |
03 | thread | tr | Switch to the specified thread. (切换到指定的线程) |
04 | threads | Print out info for every traced thread.(打印所有线程的追踪信息) |
调用栈、栈帧
序号 | 子命令 | 别名 | 描述 |
---|---|---|---|
01 | deferred | Executes command in the context of a deferred call. (在defer调用的上下文中执行一个命令) | |
01 | down | Move the current frame down. (向下移动栈帧) | |
03 | frame | Set the current frame, or execute command on a different frame. (设置当前栈帧、或在其他栈帧执行命令) | |
04 | stack | bt | Print stack trace. (打印栈追踪信息) |
05 | up | Move the current frame up. (向上移动当前栈帧) |
其他命令
序号 | 子命令 | 别名 | 描述 |
---|---|---|---|
01 | config | Changes configuration parameters. (修改配置参数) | |
02 | disassemble | disass | Disassembler. (反汇编) |
03 | dump | Creates a core dump from the current process state. (创建核心转储) | |
04 | edit | ed | |
05 | exit | quit、q | Exit the debugger. (退出调试器) |
06 | funcs | Print list of functions.(打印所有函数) | |
07 | help | h | Prints the help message. (打印帮助信息) |
08 | libraries | List loaded dynamic libraries. (列出动态链接库) | |
09 | list | ls 、l | Show source code. (打印源码) |
10 | packages | Print list of packages.(打印包列表) | |
11 | source | Executes a file containing a list of delve commands. (执行一个包含delve命令列表的文件) | |
12 | sources | Print list of source files. (打印源码路径列表) | |
13 | target | Manages child process debugging. (管理子进程调试) | |
14 | transcript | appends command output to a file. (追加命令输出到一个文件) | |
15 | types | Print list of types.(打印类型列表) |
以上高亮的子命令用的多一些
打一套组合拳(啊打!)
设置断点的方式
break 包名.函数名
b 包名.函数名
break 文件名:行号
b 文件名行号
b main.main
b main.fib
c
n
其他终端: curl http://localhost:80
描述过于诡异
bp
,查看一下断点
clear 1
,删除一个断点,并再次查看断点
c
,此时断住不动了,怎么办,怎么办?
curl http://localhost:80
当然是在其他终端输入这个啦
此时你会发现,其他终端中卡住了
此时你需要在当前终端一直
c
c
...
c下去,直到把fib函数执行完,再次断住
此时另一个终端中有结果了哦
curl http://localhost:80
StatusCode : 200
StatusDescription : OK
Content : {}
RawContent : HTTP/1.1 200 OKContent-Length: 0Date: Fri, 15 Dec 2023 15:44:06 GMT
Headers : {[Content-Length, 0], [Date, Fri, 15 Dec 2023 15:44:06 GMT]}
RawContentLength : 0
其他命令自行探索
2. debug
dlv debug ./main.go
命令参考 attach
3. exec
dlv exec ./main
命令参考 attach
Reference
https://github.com/go-delve/delve