关于go:你是使用什么工具调试-golang-程序的

54次阅读

共计 5959 个字符,预计需要花费 15 分钟才能阅读完成。

写过 C/C++ 的都是到,调试程序的时候通常应用 gdb 工具来进行调试,用起来可爽了,那么 gdb 是否也适宜 golang 程序的调试的

我集体到是通常应用 dlv 来进行 golang 程序的调试,分享一波

dlv 是什么,全称 Delve

Delve 能够让你通过控制程序的执行来与程序进行交互,他能够计算变量,并提供线程 / goroutine 状态、CPU 寄存器状态等信息

Delve 的指标是为调试 Go 程序提供一个简略弱小的调试性能

尝试看一下 dlv 的 help 信息

Usage:
  dlv [command]

Available Commands:
  attach      Attach to running process and begin debugging.
  connect     Connect to a headless debug server.
  core        Examine a core dump.
  dap         [EXPERIMENTAL] 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 command
  run         Deprecated command. Use 'debug' instead.
  test        Compile test binary and begin debugging program.
  trace       Compile and begin tracing program.
  version     Prints version.

通过 help 咱们能够看到能够应用这些命令来调试咱们的程序,依据不同的利用场景

例如,

咱们间接编译并调试的时候就能够应用 dlv debug

调试一个正在运行的程序,就能够应用 dlv attach

调试一个编译好的二进制文件,能够应用 dlv exec

其余的应用形式也相似,看上述的英文大略就晓得啥意思了

开始调试小程序

简略写一个小程序来利用一下这个调试工具

const NUM = 10

func main() {arr := make([]int, NUM)

    for i := 1; i < NUM; i++ {arr[i] = i + i
        fmt.Printf("arr[%d] == %d\n", i, arr[i])
    }
    fmt.Println("program over")
}

1、应用 dlv debug main.go 开始调试

>dlv debug main.go
Type 'help' for list of commands.
(dlv)

2、dlv 外面应用 help 查看一下能够应用哪些命令

这些命令对应的解释绝对还是比较清楚的,咱们能够来用一下

3、应用 break 打给 main 函数一个端点,或者是用 b

(dlv) b main.main
Breakpoint 1 set at 0xef84ea for main.main() d:/mycode/my_new_first/dlvtest/main.go:7

给 main 函数打 1 断点,断点号是 1

4、continue 继续执行代码,直到运行到 main 的中断

(dlv) c
> main.main() d:/mycode/my_new_first/dlvtest/main.go:7 (hits goroutine(1):1 total:1) (PC: 0xef84ea)
     2: 
     3: import "fmt"
     4: 
     5: const NUM = 10
     6: 
=>   7: func main() {8:         arr := make([]int, NUM)
     9: 
    10:         for i := 1; i < NUM; i++ {11:                 arr[i] = i + i
    12:                 fmt.Printf("arr[%d] == %d\n", i, arr[i])

5、再 打一个断点,加上具体的条件

  • b 文件: 行数
  • condition 中断号 具体的条件
(dlv) b main.go:12
Breakpoint 2 set at 0xef85a4 for main.main() d:/mycode/my_new_first/dlvtest/main.go:12
(dlv) condition 2 i==7

6、continue 继续执行代码

(dlv) c
arr[1] == 2
arr[2] == 4
arr[3] == 6
arr[4] == 8
arr[5] == 10
arr[6] == 12
> main.main() d:/mycode/my_new_first/dlvtest/main.go:12 (hits goroutine(1):1 total:1) (PC: 0xef85a4)
     7: func main() {8:         arr := make([]int, NUM)
     9: 
    10:         for i := 1; i < NUM; i++ {11:                 arr[i] = i + i
=>  12:                 fmt.Printf("arr[%d] == %d\n", i, arr[i])
    13:         }
    14:         fmt.Println("program over")
    15: }

7、locals 查看本地变量信息,p/print 打印变量信息

(dlv) locals
arr = []int len: 10, cap: 10, [...]
i = 7
(dlv) args
(no args)
(dlv) p i
7
(dlv) p arr
[]int len: 10, cap: 10, [0,2,4,6,8,10,12,14,0,0]
  • 应用 p 查看多个变量的信息,打印出具体的值

8、bp/breakpoints 查看中断列表,clear 清空中断

  • 查看中断列表
  • 清空其中一个中断
  • 再查看中断列表看看成果
(dlv) bp
Breakpoint runtime-fatal-throw (enabled) at 0xe6ca00 for runtime.throw() c:/program files/go/src/runtime/panic.go:1107 (0)
Breakpoint unrecovered-panic (enabled) at 0xe6cc80 for runtime.fatalpanic() c:/program files/go/src/runtime/panic.go:1190 (0)
        print runtime.curg._panic.arg
Breakpoint 1 (enabled) at 0xef84ea for main.main() d:/mycode/my_new_first/dlvtest/main.go:7 (1)
Breakpoint 2 (enabled) at 0xef85a4 for main.main() d:/mycode/my_new_first/dlvtest/main.go:12 (1)
        cond i == 7
(dlv) clear 2
Breakpoint 2 cleared at 0xef85a4 for main.main() d:/mycode/my_new_first/dlvtest/main.go:12
(dlv) bp
Breakpoint runtime-fatal-throw (enabled) at 0xe6ca00 for runtime.throw() c:/program files/go/src/runtime/panic.go:1107 (0)
Breakpoint unrecovered-panic (enabled) at 0xe6cc80 for runtime.fatalpanic() c:/program files/go/src/runtime/panic.go:1190 (0)
        print runtime.curg._panic.arg
Breakpoint 1 (enabled) at 0xef84ea for main.main() d:/mycode/my_new_first/dlvtest/main.go:7 (1)

9、ls 查看以后代码运行的地位,next 执行源码的下一行

(dlv) ls
> main.main() d:/mycode/my_new_first/dlvtest/main.go:12 (hits total:0) (PC: 0xef85a4)
     7: func main() {8:         arr := make([]int, NUM)
     9: 
    10:         for i := 1; i < NUM; i++ {11:                 arr[i] = i + i
=>  12:                 fmt.Printf("arr[%d] == %d\n", i, arr[i])
    13:         }
    14:         fmt.Println("program over")
    15: }
(dlv) next
> main.main() d:/mycode/my_new_first/dlvtest/main.go:12 (hits total:0) (PC: 0xef85a4)
     7: func main() {8:         arr := make([]int, NUM)
     9: 
    10:         for i := 1; i < NUM; i++ {11:                 arr[i] = i + i
    12:                 fmt.Printf("arr[%d] == %d\n", i, arr[i])
=>  13:         }
    14:         fmt.Println("program over")
    15: }

通过箭头咱们就可以看进去,没有故障

10、bt/stack 打印堆栈信息

(dlv) bt
0  0x0000000000ef85a4 in main.main
   at d:/mycode/my_new_first/dlvtest/main.go:12
1  0x0000000000e6f2f6 in runtime.main
   at c:/program files/go/src/runtime/proc.go:225
2  0x0000000000e9f3a1 in runtime.goexit
   at c:/program files/go/src/runtime/asm_amd64.s:1371

查看堆栈信息,能够间接看到汇编外面的具体信息

11、goroutines 查看程序中的协程列表,以及其对应的代码行数

(dlv) goroutines
* Goroutine 1 - User: d:/mycode/my_new_first/dlvtest/main.go:12 main.main (0xef85a4) (thread 26592)
  Goroutine 2 - User: c:/program files/go/src/runtime/proc.go:337 runtime.gopark (0xe6f6f6) [force gc (idle)]
  Goroutine 3 - User: c:/program files/go/src/runtime/proc.go:337 runtime.gopark (0xe6f6f6) [GC sweep wait]
  Goroutine 4 - User: c:/program files/go/src/runtime/proc.go:337 runtime.gopark (0xe6f6f6) [GC scavenge wait]
  Goroutine 5 - User: c:/program files/go/src/runtime/proc.go:337 runtime.gopark (0xe6f6f6) [finalizer wait]
[5 goroutines]
(dlv) goroutine
Thread 26592 at d:/mycode/my_new_first/dlvtest/main.go:12
Goroutine 1:
        Runtime: d:/mycode/my_new_first/dlvtest/main.go:12 main.main (0xef85a4)
        User: d:/mycode/my_new_first/dlvtest/main.go:12 main.main (0xef85a4)
        Go: c:/program files/go/src/runtime/asm_amd64.s:226 runtime.rt0_go (0xe9d3cc)
        Start: c:/program files/go/src/runtime/proc.go:115 runtime.main (0xe6f0e0)

goroutine 执行的时候默认是查看以后协程的信息,下面打印能够晓得,总共有 5 个协程,以后打印的协程信息是第 1 个

12、goroutine 显示以后以后协程的具体信息和切换协程

被动切换到 第 2 个协程,并查看以后协程的信息

(dlv) goroutine 2
Switched from 1 to 2 (thread 26592)
(dlv) goroutine
Thread 26592 at d:/mycode/my_new_first/dlvtest/main.go:12
Goroutine 2:
        Runtime: c:/program files/go/src/runtime/proc.go:337 runtime.gopark (0xe6f6f6)
        User: c:/program files/go/src/runtime/proc.go:337 runtime.gopark (0xe6f6f6)
        Go: c:/program files/go/src/runtime/proc.go:264 runtime.init.6 (0xe6f47c)
        Start: c:/program files/go/src/runtime/proc.go:267 runtime.forcegchelper (0xe6f4a0)
(dlv) goroutines
  Goroutine 1 - User: d:/mycode/my_new_first/dlvtest/main.go:12 main.main (0xef85a4) (thread 26592)
* Goroutine 2 - User: c:/program files/go/src/runtime/proc.go:337 runtime.gopark (0xe6f6f6) [force gc (idle)]
  Goroutine 3 - User: c:/program files/go/src/runtime/proc.go:337 runtime.gopark (0xe6f6f6) [GC sweep wait]
  Goroutine 4 - User: c:/program files/go/src/runtime/proc.go:337 runtime.gopark (0xe6f6f6) [GC scavenge wait]
  Goroutine 5 - User: c:/program files/go/src/runtime/proc.go:337 runtime.gopark (0xe6f6f6) [finalizer wait]
[5 goroutines]

工具须要用起来才有意义

好了,本次就到这里

技术是凋谢的,咱们的心态,更应是凋谢的。拥抱变动,背阴而生,致力向前行。

我是 阿兵云原生,欢送点赞关注珍藏,下次见~

正文完
 0