← 返回文章

Golang 调试工具——dlv

简单介绍了一些 dlv 的命令及其含义。

Delve 是 Go 编程语言的调试器。

安装

  1. 下载dlv

    git clone https://github.com/go-delve/delve.git $GOPATH/src/github.com/go-delve/delve

或者

go get github.com/derekparker/delve/cmd/dlv


2. 安装

cd $GOPATH/src/github.com/go-delve/delve make install

  1. 验证是否安装成功

    $ dlv version 
    Delve Debugger 
    Version: 1.7.2 
    Build: $Id: 5b6f24e7fbcad3fe3bc574d3763b2f20afa1d6a1 $
    

使用手册

获取帮助 执行 dlv -h

执行 dlv help + 具体命令 来查看详细说明,

例如:dlv help attach 来查看 attach 的使用方式。

进入调试模式

  1. dlv attach <pid> :对正在运行的进程直接进行调试(pid为进程号):

  2. dlv debug [package]:在禁用优化的情况下编译程序,启动并 attach 到它。

  3. dlv exec <exe> :执行预编译的二进制文件并开始 debug 会话。

    这个执行的二进制文件在其编译是需要禁止优化的。具体操作在 补充内容 中有写。

  4. dlv core <executable> <core> [flags]:Examine a core dump (only supports linux and windows core dumps). 不是很懂。

  5. dlv test [package]:用于调试 test 文件的。

    dlv trace 追调用轨迹 dlv trace [package]:可以追踪代码中函数的调用轨迹。

    package main 
    import ( "fmt" "time" ) 
    func Test() { fmt.Println("hello") time.Sleep(1000 * 1000 * 100) } 
    func Test2() { fmt.Println("world") time.Sleep(1000 * 1000 * 100) } 
    func main() { 
      for i := 0; i < 2; i++ { 
        go Test() 
        go Test2() 
      } 
      time.Sleep(1000 * 1000 * 2000) 
      fmt.Println("end") 
    }
    

这部分代码,我们创建了两个函数,Test 和 Test2。同时在主函数中创建四个协程来执行它们。

$ dlv trace hello.go Test
goroutine(19): main.Test2()
goroutine(21): main.Test2()
goroutine(18): main.Test()
world
hello
world
goroutine(20): main.Test()
hello
=> ()
=> ()
=> ()
=> ()
end

Trace 命令可以添加正则表达式的参数,在这个命令中添加的是 Test,所以除了Test,Test2也被追踪到了。

补充内容

禁止优化:原因是 golang 在编译过程中会对某些代码进行优化,这可能会导致实际运行代码与源代码不匹配的情况,那这部分不匹配的代码(如被内联优化的代码)就没法对其进行 debug。所以我们在debug时,通常情况需要禁止优化。

Golang 在编译时,也提供了进展优化的参数: go build -gcflags="all=-N -l" -o bin/app

  • go build 可以用 -gcflags 给 go 编译器传入参数,也就是传给 go tool compile 的参数,因此可以用 go tool compile --help 查看所有可用的参数。

  • "all=-N -l" 表示对所有包的编译应用 -N 和 -l。 执行 go tool compile --help 可以看到 -N 和 -l 的作用:

    -N disable optimizations # 禁用优化 
    -l disable inlining # 禁用内联优化。
    

使用 -m 可以查看编译器优化决策

调试模式基本命令

常用命令

  1. b(break):break [name] [linespec] 设置一个断点。
示例如下:
b Test
b test.go:13
  1. r(restart):重启当前进程。

    如果刚执行了 dlv debug hello.go 无需执行此命令。如果进程已经结算或需要重新开始,则需要执行r。

  2. c(continue):继续执行到下一个断点处。

  3. bp(breakpoints):查看所有断点。

  4. on: on <breakpoint name or id> trace: 当运行到某断点时执行相应命令。

示例:
on 3 p i
指的是对运行到断点3的时候打印变量 i。
  1. cond(condition):有条件的断点。针对某个断点,只有表达式成立才会被中断。
示例如下:
condition 3 i==1
  1. n(next): 逐行执行代码,不进入函数内。
  2. s(step): 逐行执行代码,遇到函数会跳进内部。
  3. stepout : 当使用 s 命令进入某个函数后,执行它可跳出函数。
  4. si(step-instruction) : 单步单核执行代码。
  5. args : 查看被调用函数所传入的参数值。
  6. locals: 查看所有局部变量。
  7. clear: 清除单个断点。
  8. clearall: 清除多个断点。
  9. list: 打印当前断点位置的源代码。
  10. bt: 打印当前栈信息。 多协程调试
  11. goroutines: 显示所有协程。
  12. goroutine: 切换协程。 goroutine 7 ##表示切换到 7 号协程上。

其他命令

  1. frame:切换栈。

  2. regs: 打印寄存器内容。

  3. sources:打印所有源代码文件路径。

  4. source:执行一个含有dlv命令的文件。

  5. trace:类似于打断点,但不会中断,同时会输出一行提示信息。

    参考文章:

    GO语言调试利器dlv快速上手 - 一觉醒来写程序 - 博客园

    delve/Documentation at master · go-delve/delve

\