天天看点

使用Delve进行Golang代码的调试安装调试代码进阶调试

追踪代码中的错误可能是一件非常头疼的事情。这在高度依赖goroutine的golang代码调试中更加的突出。有一个趁手的 debug 工具就显得非常的重要。我们先来看看 go 官方的debug tool文档写的啥。

gdb does not understand go programs well. the stack management, threading, and runtime contain aspects that differ enough from the execution model gdb expects that they can confuse the debugger, even when the program is compiled with gccgo. in short, the instructions below should be taken only as a guide to how to use gdb when it works, not as a guarantee of success. in time, a more go-centric debugging architecture may be required.

总结一下上面说的话。

go 的debug工具有gdb这个玩意,但是目前貌似工作的不咋滴

目前官方只是给你介绍介绍这个玩意怎么用,但是不保证能成功

实话说,我们需要一个更懂 go 的调试器

delve目的就是为了解决开发者在使用 gdb 调试中遇到的各种各样的问题。我们开始详细的介绍一些使用delve 调试代码的例子。

首先默认你已经安装了 go 环境,安装命令很简单,一句话。

注意:如果你使用go1.5,你必须在运行这个命令前设置<code>go15vendorexperiment=1</code>

首先得说明一下,实诚点说,当你想用debug 工具的时候,你的代码估计已经不按照你想象的方式运行了。只是你不知道为什么会这样,因此你可能需要换一种方式启动你的程序,下面我们来演示一下如果使用<code>dlv</code>来启动你的程序。我们的示例代码如下:

在这个示例代码中,我们创建了10个<code>goroutine</code>,这种代码对于 gdb 来说是几乎不可读的,因为它对于<code>goroutine</code>的支持很差。但是<code>delve</code>作为一个专业的 go 调试器,对于<code>goroutine</code>这种杀手级功能还是非常了解的。下面我们来启动程序。

运行这个命令,dlv会去编译你的代码,然后传一些参数给编译器,好让编译器编译出来更加方便调试的可执行文件,然后启动了你的程序,并且<code>attach</code>上去,这样你的console就会停留在了<code>debug session</code>,下面就可以调试程序了。

首先我们在main函数上设置一个断点。

输出信息里面告诉了我们断点的 id和断点的位置,函数名和文件名以及所在行数。我们使用<code>continue</code>命令让程序运行到我们打断点的地方。

现在程序就停在了第一个断点,现在我们可以使用<code>next</code>命令让程序运行到下一句话,如果你想继续向下,可以直接按回车(delve会重复上一条命令如果你按下回车键)。

现在我们可以尝试使用<code>print</code>命令去看一下变量的值。

同时你也可以输出一个表达式

下面我们在另外一个函数<code>dostuff</code>上设置一个断点

我们使用<code>continue</code>到我们设置断点的地方,然后<code>next</code>

可以看到delve会告诉你目前的goroutine id,我们试试输出一下i和wg.

我们创建了10个goroutine,如果你继续使用next,你会发现你还是在同一个goroutine下。这样就避免了被调试器跳转到了另外的goroutine下导致不必要的调试错误。可见还是为 go 而生的调试器才是真爱啊。

其实很多时候,我们调试的代码可能是<code>daemon</code>程序或者需要实现编译好在不同机器运行的程序。这就需要我们<code>attach</code>到一个已经在运行中的程序上,下面我们就使用上面的代码来演示一下如何<code>attach</code>到一个程序上进行调试。首先将刚才的程序运行起来,我这里直接使用了

然后使用ps查看正在运行的程序pid

然后我们<code>attach</code>上去

可以看到,熟悉的<code>debug seesion</code>又回来了。下面我们可以继续使用上面的命令去设置断点了

我使用<code>continue</code>使程序运行到我设置断点的地方

可以看到,delve已经打印出来了当前正在运行的goroutine,下面我们<code>print</code>一下我们当前的i

和上面一样,而且<code>attach</code>到这个进程后,也可以把对应的源码显示出来,是不是很强大呢。更多的功能就自己参考文档摸索吧。