dlv 调试

Administrator
发布于 2023-09-11 / 120 阅读 / 0 评论 / 0 点赞

dlv 调试

DLV

在 Go 编程语言中,DLV (Delve) 是一种用于调试 Go 代码的工具。DLV 是一个开源的调试器,它可以帮助开发者在编写和调试 Go 程序时识别和解决问题。以下是关于使用 DLV 进行 Go 代码调试的一些重要信息:

  • 设置断点: 开发者可以在他们的 Go 代码中设置断点,以便在程序执行时停止并检查变量、堆栈跟踪和其他调试信息。

  • 单步执行: DLV 允许用户逐行或逐过程地执行代码,以便一步一步地跟踪程序的执行流程。

  • 查看变量: 开发者可以使用 DLV 查看当前执行上下文中的变量的值,以便了解程序的状态。

  • 检查堆栈: DLV 允许用户查看当前函数的调用堆栈,以识别可能的错误或异常。

  • 多线程调试: Go 支持并发编程,DLV 也可以用于调试多线程应用程序,以帮助解决并发问题。

  • 远程调试: DLV 支持远程调试,这意味着您可以在远程服务器上调试运行中的 Go 代码。

  • 集成编辑器: DLV 可以与一些流行的集成开发环境(IDE)和文本编辑器集成,例如 Visual Studio Code(VS Code)和 GoLand。

安装

使用install安装,之后会安装在GOPATH目录下

go install  github.com/go-delve/delve/cmd/dlv

如果在/etc/profile下设置了PATH则可以直接使用,没有则需要设置全局变量

export PATH=$PATH:/c/Users/54225/go/bin/

运行

这里展示一个运行demo

#cat main.go
package main

import "fmt"

func main() {
	i := []int{1, 2, 3, 4, 5, 6, 7, 8}
	j := "this is dlv"

	for _, v := range i {
		fmt.Println(v)
	}

	fmt.Println(j)
}

执行debug运行,执行完毕后就是这个样子,此时程序还没有被运行

$ dlv.exe debug ch19/main.go
Type 'help' for list of commands.
(dlv)

执行c运行程序,发现程序立刻执行完毕了,这里的c是命令call简写

$ dlv.exe debug ch19/main.go 
Type 'help' for list of commands.
(dlv) c
1
2
3
4
5
6
7
8
this is dlv
Process 20804 has exited with status 0

执行b标记断点,断点表示执行到这边停顿

$ dlv.exe debug ch19/main.go 
Type 'help' for list of commands.
(dlv) b main.go:5
Breakpoint 1 set at 0xf49812 for main.main() C:/Users/54225/AppData/Roaming/MobaXterm/home/project/learning/ch19/main.go:5

在标记断点后,需要运行程序才可以触发断点

$ dlv.exe debug ch19/main.go 
Type 'help' for list of commands.
(dlv) b main.go:5
Breakpoint 1 set at 0xf49812 for main.main() C:/Users/54225/AppData/Roaming/MobaXterm/home/project/learning/ch19/main.go:5
(dlv) c
> main.main() C:/Users/54225/AppData/Roaming/MobaXterm/home/project/learning/ch19/main.go:5 (hits goroutine(1):1 total:1) (PC: 0xf49812)
     1: package main
     2:
     3: import "fmt"
     4:
=>   5: func main() {
     6:         i := []int{1, 2, 3, 4, 5, 6, 7, 8}
     7:         j := "this is dlv"
     8:
     9:         for _, v := range i {
    10:                 fmt.Println(v)

显示在main.go5行停顿,此时按n继续

(dlv) n
> main.main() C:/Users/54225/AppData/Roaming/MobaXterm/home/project/learning/ch19/main.go:6 (PC: 0xf49829)
     1: package main
     2:
     3: import "fmt"
     4:
     5: func main() {
=>   6:         i := []int{1, 2, 3, 4, 5, 6, 7, 8}
     7:         j := "this is dlv"
     8:
     9:         for _, v := range i {
    10:                 fmt.Println(v)
    11:         }

发现执行到下一行了,此时打印i变量看看,发现没有找到这个变量,那是因为这一行没执行,需要到下一行打印才能生效

(dlv) p i
Command failed: could not find symbol value for i

在下一行打印生效了

(dlv) n
> main.main() C:/Users/54225/AppData/Roaming/MobaXterm/home/project/learning/ch19/main.go:7 (PC: 0xf498dc)
     2:
     3: import "fmt"
     4:
     5: func main() {
     6:         i := []int{1, 2, 3, 4, 5, 6, 7, 8}
=>   7:         j := "this is dlv"
     8:
     9:         for _, v := range i {
    10:                 fmt.Println(v)
    11:         }
    12:
(dlv) p i
[]int len: 8, cap: 8, [1,2,3,4,5,6,7,8]

一直按nfmt.Println(v)这一行,这是一个包函数,可以按s进入下一层

(dlv) n
> main.main() C:/Users/54225/AppData/Roaming/MobaXterm/home/project/learning/ch19/main.go:10 (PC: 0xf49965)
     5: func main() {
     6:         i := []int{1, 2, 3, 4, 5, 6, 7, 8}
     7:         j := "this is dlv"
     8:
     9:         for _, v := range i {
=>  10:                 fmt.Println(v)
    11:         }
    12:
    13:         fmt.Println(j)
    14: }
(dlv) s
> fmt.Println() C:/Users/54225/AppData/Roaming/MobaXterm/home/go1.20.5.windows-amd64/go/src/fmt/print.go:313 (PC: 0xf444ca)
   308: }
   309:
   310: // Println formats using the default formats for its operands and writes to standard output.
   311: // Spaces are always added between operands and a newline is appended.
   312: // It returns the number of bytes written and any write error encountered.
=> 313: func Println(a ...any) (n int, err error) {
   314:         return Fprintln(os.Stdout, a...)
   315: }
   316:
   317: // Sprintln formats using the default formats for its operands and returns the resulting string.
   318: // Spaces are always added between operands and a newline is appended.

进入下一层后,看到想看的逻辑了,想要返回到主函数,需要按n,结束这一次返回

(dlv) n
> fmt.Println() C:/Users/54225/AppData/Roaming/MobaXterm/home/go1.20.5.windows-amd64/go/src/fmt/print.go:314 (PC: 0xf444ff)
   309:
   310: // Println formats using the default formats for its operands and writes to standard output.
   311: // Spaces are always added between operands and a newline is appended.
   312: // It returns the number of bytes written and any write error encountered.
   313: func Println(a ...any) (n int, err error) {
=> 314:         return Fprintln(os.Stdout, a...)
   315: }
   316:
   317: // Sprintln formats using the default formats for its operands and returns the resulting string.
   318: // Spaces are always added between operands and a newline is appended.
   319: func Sprintln(a ...any) string {
(dlv) n
1
> main.main() C:/Users/54225/AppData/Roaming/MobaXterm/home/project/learning/ch19/main.go:10 (PC: 0xf49a05)
Values returned:
        n: 2
        err: error nil

     5: func main() {
     6:         i := []int{1, 2, 3, 4, 5, 6, 7, 8}
     7:         j := "this is dlv"
     8:
     9:         for _, v := range i {
=>  10:                 fmt.Println(v)
    11:         }
    12:
    13:         fmt.Println(j)
    14: }

想要结束此次任务,不看断点了,可以按c

(dlv) n
1
> main.main() C:/Users/54225/AppData/Roaming/MobaXterm/home/project/learning/ch19/main.go:10 (PC: 0xf49a05)
Values returned:
        n: 2
        err: error nil

     5: func main() {
     6:         i := []int{1, 2, 3, 4, 5, 6, 7, 8}
     7:         j := "this is dlv"
     8:
     9:         for _, v := range i {
=>  10:                 fmt.Println(v)
    11:         }
    12:
    13:         fmt.Println(j)
    14: }
(dlv) c
2
3
4
5
6
7
8
this is dlv
Process 20716 has exited with status 0

此时程序已经执行完毕了,但是debug模式没有退出,可以按r重新启动

(dlv) r
Process restarted with PID 25312
(dlv) c
> main.main() C:/Users/54225/AppData/Roaming/MobaXterm/home/project/learning/ch19/main.go:5 (hits goroutine(1):1 total:1) (PC: 0xf49812)
     1: package main
     2:
     3: import "fmt"
     4:
=>   5: func main() {
     6:         i := []int{1, 2, 3, 4, 5, 6, 7, 8}
     7:         j := "this is dlv"
     8:
     9:         for _, v := range i {
    10:                 fmt.Println(v)

如果下次执行不希望有断点了,可以按clear 1,删除第一个断点也可以clearall删除全部断点,按b查看断点

(dlv) b
Breakpoint 5 set at 0x7ff948b60911 for :0

(dlv) clear 5
Breakpoint 5 cleared at 0x7ff948b60911 for :0

(dlv) clearall
Breakpoint 4 cleared at 0x0 for :0
Breakpoint 2 cleared at 0xf49812 for main.main() C:/Users/54225/AppData/Roaming/MobaXterm/home/project/learning/ch19/main.go:5