英文:
How do I debug a program written in the Go language?
问题
我如何调试Go程序?我一直在使用Gedit Go IDE,但它没有调试功能。有没有一种方法可以逐步执行我的代码并检查内存?还是我只能使用打印语句?我可以使用OutputDebugString吗?
英文:
How do I debug a Go program? I have been using the Gedit Go IDE, but it doesn't have debugging. Is there a way to step though my code and inspect memory? Or am I stuck with print statements? Can I use OutputDebugString?
答案1
得分: 23
更新:现在文档中有一个官方页面介绍如何使用GDB调试Go代码。自从写下这个答案以来,有很多变化,下面列出的一些限制已经被移除。我将保留这个答案的其余部分以供参考,但如果你想要调试Go代码,请点击上面的链接。
Go链接器现在会生成可以被GDB 7.x版本解释的DWARF调试符号。
以下是上面链接的博客文章中的亮点:
你可以...
- 在GDB 7.x版本中加载Go程序
- 按行列出所有Go、C和汇编源文件(Go运行时的部分是用C和汇编语言编写的)
- 按行设置断点并逐步执行代码
- 打印堆栈跟踪和检查堆栈帧
- 查找变量的地址并打印其内容
仍然存在一些不便之处:
- 生成的DWARF代码无法被Mac OS X附带的GDB 6.x版本解读。我们非常乐意接受修补程序,使DWARF输出与标准的OS X GDB兼容,但在修复之前,您需要下载、构建和安装GDB 7.x版本才能在OS X下使用它。源代码可以在http://sourceware.org/gdb/download/找到。由于OS X的特殊性,您需要将二进制文件安装在具有chgrp procmod和chmod g+s权限的本地文件系统上。
- 变量名带有包名的限定符,由于GDB不理解Go包,您必须使用完整的名称引用每个项目。例如,包main中的变量v必须被引用为'main.v',用单引号括起来。这样做的一个后果是变量和函数名的制表符自动补全无法工作。
- 词法作用域信息有些混淆。如果有多个同名变量,第n个实例将具有形式为“#n”的后缀。我们计划修复这个问题,但需要对编译器和链接器之间交换的数据进行一些更改。
- 切片和字符串变量在运行时库中以其底层结构表示。它们看起来类似于{data = 0x2aaaaab3e320, len = 1, cap = 1}。对于切片,您必须解引用数据指针以检查元素。
有些功能无法使用:
- 无法检查通道、函数、接口和映射变量。
- 只有Go变量带有类型信息;运行时的C变量没有。
- Windows和ARM二进制文件不包含DWARF调试信息,因此无法使用GDB进行检查。
英文:
Update: There is now an official page in the docs on Debugging Go Code with GDB. Much has changed since this answer was written, and several of the limitations listed below have been removed. I'm leaving the rest of this answer for posterity, but if you want to debug Go code, follow the link above.
The Go linkers now emit DWARF debugging symbols that can be interpreted by gdb version 7.x.
Highlight from the blog post linked above:
You can...
- load a Go program in GDB version 7.x
- list all Go, C, and assembly source files by line (parts of the Go runtime are written in C and assembly),
- set breakpoints by line and step through the code,
- print stack traces and inspect stack frames, and
- find the addresses and print the contents of most variables.
There are still some inconveniences:
- The emitted DWARF code is unreadable by the GDB version 6.x that ships with Mac OS X. We would gladly accept patches to make the DWARF output compatible with the standard OS X GDB, but until that’s fixed you’ll need to download, build, and install GDB 7.x to use it under OS X. The source can be found at http://sourceware.org/gdb/download/. Due to the particulars of OS X you’ll need to install the binary on a local file system with chgrp procmod and chmod g+s.
- Names are qualified with a package name and, as GDB doesn't understand Go packages, you must reference each item by its full name. For example, the variable named v in package main must be referred to as 'main.v', in single quotes. A consequence of this is that tab completion of variable and function names does not work.
- Lexical scoping information is somewhat obfuscated. If there are multiple variables of the same name, the nth instance will have a suffix of the form ‘#n’. We plan to fix this, but it will require some changes to the data exchanged between the compiler and linker.
- Slice and string variables are represented as their underlying structure in the runtime library. They will look something like {data = 0x2aaaaab3e320, len = 1, cap = 1}. For slices, you must dereference the data pointer to inspect the elements.
Some things don't work:
-
Channel, function, interface, and map variables cannot be inspected.
-
Only Go variables are annotated with type information; the runtime's C variables are not.
-
Windows and ARM binaries do not contain DWARF debugging information and, as such, cannot be inspected with GDB.
答案2
得分: 15
新的倡议(从2014年5月开始):derekparker/delve
,现在(2021年):go-delve/delve:
> Delve是一个用Go语言编写的Go调试器。
(主要用于Linux,尽管OsX支持即将到来,Windows支持<del>未知</del> 在2016年支持)
特点
> - 附加到已经运行的进程
- 启动进程并开始调试会话
- 设置断点,单步执行,跳过函数,打印变量内容
用法
> 调试器可以通过三种方式启动:
> 编译、运行和附加一步完成:
$ dlv -run
> 提供要调试的程序的名称,调试器将为您启动它。
$ dlv -proc path/to/program
> 提供当前正在运行的进程的pid,调试器将附加并开始会话。
$ sudo dlv -pid 44839
断点
> Delve可以在调试会话中使用断点命令插入断点,但为了方便调试,您也可以调用runtime.Breakpoint()
,Delve将处理断点并在下一行源代码处停止程序。
英文:
New initiative (started May 2014): derekparker/delve
, now (2021): go-delve/delve:
> Delve is a Go debugger, written in Go.
(mainly for Linux though, OsX support is coming, Windows support <del>unknown</del> supported in 2016)
Features
> - Attach to an already running process
- Launch a process and begin debug session
- Set breakpoints, single step, step over functions, print variable contents
Usage
> The debugger can be launched in three ways:
> Compile, run, and attach in one step:
$ dlv -run
> Provide the name of the program you want to debug, and the debugger will launch it for you.
$ dlv -proc path/to/program
> Provide the pid of a currently running process, and the debugger will attach and begin the session.
$ sudo dlv -pid 44839
Breakpoints
> Delve can insert breakpoints via the breakpoint command once inside a debug session, however for ease of debugging, you can also call runtime.Breakpoint()
and Delve will handle the breakpoint and stop the program at the next source line.
答案3
得分: 9
另一个用于Go调试会话的工具是:hopwatch
> 与大多数调试器不同,hopwatch要求您在程序的感兴趣的点插入函数调用。在这些程序位置,您可以告诉Hopwatch显示变量值并暂停程序(或goroutine)。
Hopwatch使用Websockets在您的程序和在HTML5页面中运行的调试器之间交换命令。
(因此,它仍然类似于“打印语句”,但以更优雅的方式查看结果,而不会污染stdout
和stderr
)
> 当您的程序调用Break函数时,它会将调试信息发送到浏览器页面并等待用户交互。
使用函数Display
,Printf
或Dump
(go-spew
),您可以在浏览器页面上记录信息。
在hopwatch页面上,开发人员可以查看调试信息并选择恢复程序的执行。
英文:
Another initiative for go debugging session: hopwatch
> Unlike most debuggers, hopwatch requires you to insert function calls at points of interest in your program. At these program locations, you can tell Hopwatch to display variable values and suspend the program (or goroutine).
Hopwatch uses Websockets to exchange commands between your program and the debugger running in a HTML5 page.
(so it is still similar to "print statement" but with a more elegant way to see the result without polluting stdout
and stderr
)
> When your program calls the Break function, it sends debug information to the browser page and waits for user interaction.
Using the functions Display
, Printf
or Dump
(go-spew
), you can log information on the browser page.
On the hopwatch page, the developer can view debug information and choose to resume the execution of the program.
答案4
得分: 8
也许一些逐步指南可以帮助你开始使用GDB。
我创建了一个名为silly.go的文件,其中包含以下内容:
package main
import "fmt"
func x() {
foo := 5
fmt.Printf("foo: %v\n", foo)
}
func main() {
go x()
fmt.Printf("Done.\n")
}
在运行8g silly.go
和8l -o silly silly.8
之后,我可以运行gdb silly
。(我使用的是Ubuntu 11.04 32位自带的“GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2”。)
然后,我可以输入list
、b 7
(break 7
的简写)和run
。它会在第7行停下来,然后我可以运行:
(gdb) p foo
$1 = 5
有趣的是,看看Eclipse/CDT调试器和/或DDD是否能与Go一起使用。
英文:
Perhaps some step by step instructions for getting started with GDB would help.
I created silly.go containing:
package main
import "fmt"
func x() {
foo := 5
fmt.Printf("foo: %v\n", foo)
}
func main() {
go x()
fmt.Printf("Done.\n")
}
After running 8g silly.go
and 8l -o silly silly.8
, I can run gdb silly
. (I have "GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2" that as far as I know came with Ubuntu 11.04 32 bit.)
I can then type list
, b 7
(short for break 7
), and run
. It stops at line 7, and I can run:
(gdb) p foo
$1 = 5
It would be interesting to see if the Eclipse/CDT debugger and/or DDD would work with Go.
答案5
得分: 5
GDB 7.5 正式支持 Go 语言。
英文:
GDB 7.5 officially supports Go.
答案6
得分: 3
有一个实验性的调试器包叫做ogle。不确定它的工作效果如何。
英文:
There is an experimental debugger package called ogle. Not sure how well it works.
答案7
得分: 3
很不幸,但目前最好的方法是使用打印函数。内置的print和println会起作用,但根据您所需的信息,fmt中的函数有时会更好。
英文:
It's unfortunate, but the best way right now is to use print functions. The built-in print and println will work, but the functions in fmt will sometimes work better depending on what information you're after.
答案8
得分: 3
另一种正在开发中的调试技术(2014年第四季度):Go执行跟踪器
> 跟踪包含以下内容:
> - 与goroutine调度相关的事件:
- 一个goroutine在处理器上开始执行,
- 一个goroutine在同步原语上阻塞,
- 一个goroutine创建或解除阻塞另一个goroutine;
- 与网络相关的事件:
- 一个goroutine在网络IO上阻塞,
- 一个goroutine在网络IO上解除阻塞;
- 与系统调用相关的事件:
- 一个goroutine进入系统调用,
- 一个goroutine从系统调用返回;
- 与垃圾回收器相关的事件:
- 垃圾回收开始/停止,
- 并发扫描开始/停止;以及
- 用户事件。
> 通过“处理器”我指的是逻辑处理器,即GOMAXPROCS
的单位。
每个事件包含事件ID、精确时间戳、操作系统线程ID、处理器ID、goroutine ID、堆栈跟踪和其他相关信息(例如解除阻塞的goroutine ID)。
<a href="https://lh5.googleusercontent.com/w0znUT_0_xbipG_UlQE5Uc4PbC8Mw1duHRLg_AKTOS4iS6emOD6jnQvSDACybOfCbuSqr2ulkxULXGOBQpZ2IejPHW_8NHufqmn8q5u-fF_MSMCEgu6FwLNtMvowbq74nA">
</a>
英文:
Another debug technique being developed (Q4 2014): Go Execution Tracer
> The trace contains
> - events related to goroutine scheduling:
- a goroutine starts executing on a processor,
- a goroutine blocks on a synchronization primitive,
- a goroutine creates or unblocks another goroutine;
- network-related events:
- a goroutine blocks on network IO,
- a goroutine is unblocked on network IO;
- syscalls-related events:
- a goroutine enters into syscall,
- a goroutine returns from syscall;
- garbage-collector-related events:
- GC start/stop,
- concurrent sweep start/stop; and
- user events.
> By "processor" I mean a logical processor, unit of GOMAXPROCS
.
Each event contains event id, a precise timestamp, OS thread id, processor id, goroutine id, stack trace and other relevant information (e.g. unblocked goroutine id).
<a href="https://lh5.googleusercontent.com/w0znUT_0_xbipG_UlQE5Uc4PbC8Mw1duHRLg_AKTOS4iS6emOD6jnQvSDACybOfCbuSqr2ulkxULXGOBQpZ2IejPHW_8NHufqmn8q5u-fF_MSMCEgu6FwLNtMvowbq74nA">
</a>
答案9
得分: 1
获取JetBrains Toolbox,下载GoLand,在编辑器的左侧单击,它将设置一个断点。
英文:
Get the JetBrains Toolbox, download GoLand, click on the left side of the editor, and it'll set a breakpoint.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论