简体   繁体   English

如何调试用 Go 语言编写的程序?

[英]How do I debug a program written in the Go language?

How do I debug a Go program?如何调试 Go 程序? I have been using the Gedit Go IDE , but it doesn't have debugging.我一直在使用Gedit Go IDE ,但它没有调试功能。 Is there a way to step though my code and inspect memory?有没有办法遍历我的代码并检查内存? Or am I stuck with print statements?还是我坚持打印语句? Can I use OutputDebugString ?我可以使用OutputDebugString吗?

Update : There is now an official page in the docs on Debugging Go Code with GDB .更新:现在在使用 GDB 调试 Go 代码的文档中有一个官方页面。 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.我将这个答案的其余部分留给后人,但如果您想调试 Go 代码,请点击上面的链接。

The Go linkers now emit DWARF debugging symbols that can be interpreted by gdb version 7.x. Go 链接器现在发出可由 gdb 7.x 版解释的 DWARF 调试符号。

Highlight from the blog post linked above:从上面链接的博客文章中突出显示:

You can...你可以...

  • load a Go program in GDB version 7.x在 GDB 7.x 版中加载 Go 程序
  • list all Go, C, and assembly source files by line (parts of the Go runtime are written in C and assembly),逐行列出所有 Go、C 和汇编源文件(Go 运行时的一部分是用 C 和汇编编写的),
  • 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/ . Mac OS X 附带的 GDB 6.x 版无法读取发出的 DWARF 代码。我们很乐意接受补丁以使 DWARF 输出与标准 OS X GDB 兼容,但在修复之前,您需要下载、构建,并安装 GDB 7.x 以在 OS X 下使用它。源可以在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.由于 OS X 的特殊性,您需要使用 chgrp procmod 和 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.名称由包名限定,由于 GDB 不理解 Go 包,您必须通过其全名引用每个项目。 For example, the variable named v in package main must be referred to as 'main.v', in single quotes.例如,包 main 中名为 v 的变量必须用单引号表示为“main.v”。 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'.如果有多个同名变量,则第 n 个实例将具有“#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}.它们看起来像 {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;只有 Go 变量被标注了类型信息; the runtime's C variables are not.运行时的 C 变量不是。
  • Windows and ARM binaries do not contain DWARF debugging information and, as such, cannot be inspected with GDB. Windows 和 ARM 二进制文件不包含 DWARF 调试信息,因此无法使用 GDB 进行检查。

New initiative (started May 2014): derekparker/delve , now (2021): go-delve/delve :新计划(2014 年 5 月开始): derekparker/delve ,现在(2021 年): go-delve/delve

Delve is a Go debugger, written in Go . Delve 是一个Go 调试器,用 Go 编写
(mainly for Linux though, OsX support is coming, Windows support (不过主要是针对 Linux,OsX 支持即将到来,Windows 支持unknown未知supported in 2016 ) 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.提供当前正在运行的进程的 pid,调试器将附加并开始会话。

$ 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. Delve 可以在调试会话中一次通过 breakpoint 命令插入断点,但是为了便于调试,您也可以调用runtime.Breakpoint() ,Delve 将处理断点并在下一个源代码行停止程序。

Another initiative for go debugging session: hopwatch Go 调试会话的另一个举措: hopwatch

Unlike most debuggers, hopwatch requires you to insert function calls at points of interest in your program.与大多数调试器不同,hopwatch 要求您在程序中感兴趣的点插入函数调用。 At these program locations, you can tell Hopwatch to display variable values and suspend the program (or goroutine).在这些程序位置,您可以告诉 Hopwatch 显示变量值并挂起程序(或 goroutine)。
Hopwatch uses Websockets to exchange commands between your program and the debugger running in a HTML5 page. Hopwatch 使用 Websockets 在您的程序和运行在 HTML5 页面中的调试器之间交换命令。

(so it is still similar to "print statement" but with a more elegant way to see the result without polluting stdout and stderr ) (所以它仍然类似于“打印语句”,但以更优雅的方式查看结果而不污染stdoutstderr

跳表

When your program calls the Break function, it sends debug information to the browser page and waits for user interaction.当您的程序调用 Break 函数时,它会将调试信息发送到浏览器页面并等待用户交互。
Using the functions Display , Printf or Dump ( go-spew ), you can log information on the browser page.使用DisplayPrintfDump ( go-spew ) 功能,您可以在浏览器页面上记录信息。
On the hopwatch page, the developer can view debug information and choose to resume the execution of the program.在hopwatch页面,开发者可以查看调试信息并选择继续执行程序。

有来源

Perhaps some step by step instructions for getting started with GDB would help.也许一些 GDB 入门的分步说明会有所帮助。

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 .运行8g silly.go8l -o silly silly.8 ,我可以运行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.) (我有“GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2”,据我所知随 Ubuntu 11.04 32 位一起提供。)

I can then type list , b 7 (short for break 7 ), and run .然后我可以输入listb 7break 7缩写),然后run It stops at line 7, and I can run:它停在第 7 行,我可以运行:

(gdb) p foo
$1 = 5

It would be interesting to see if the Eclipse/CDT debugger and/or DDD would work with Go.看看 Eclipse/CDT 调试器和/或 DDD 是否可以与 Go 一起工作会很有趣。

GDB 7.5正式支持 Go。

Another debug technique being developed (Q4 2014): Go Execution Tracer另一种正在开发的调试技术(2014 年第四季度): Go Execution Tracer

The trace contains跟踪包含

  • events related to goroutine scheduling :与 goroutine 调度相关的事件
    • a goroutine starts executing on a processor, goroutine 开始在处理器上执行,
    • a goroutine blocks on a synchronization primitive,一个 goroutine 阻塞在同步原语上,
    • a goroutine creates or unblocks another goroutine;一个 goroutine 创建或解除阻塞另一个 goroutine;
  • network-related events :网络相关事件
    • a goroutine blocks on network IO,一个 goroutine 阻塞网络 IO,
    • a goroutine is unblocked on network IO;一个 goroutine 在网络 IO 上被解锁;
  • syscalls-related events :系统调用相关事件
    • a goroutine enters into syscall,一个 goroutine 进入系统调用,
    • a goroutine returns from syscall;一个 goroutine 从 syscall 返回;
  • garbage-collector-related events :垃圾收集器相关事件
    • GC start/stop, GC 启动/停止,
    • concurrent sweep start/stop;并发扫描开始/停止; and
  • user events .用户事件

By "processor" I mean a logical processor, unit of GOMAXPROCS . “处理器”是指逻辑处理器,即GOMAXPROCS单元。
Each event contains event id, a precise timestamp, OS thread id, processor id, goroutine id, stack trace and other relevant information (eg unblocked goroutine id).每个事件包含事件 id、精确的时间戳、操作系统线程 id、处理器 id、goroutine id、堆栈跟踪和其他相关信息(例如未阻塞的 goroutine id)。

https://lh5.googleusercontent.com/w0znUT_0_xbipG_UlQE5Uc4PbC8Mw1duHRLg_AKTOS4iS6emOD6jnQvSDACybOfCbuSqr2ulkxULXGOBQpZ2IejPHW_8NHufqmn8qLw4PbC8Mw1duHRLg_AKTOS4iS6emOD6

There is an experimental debugger package called ogle .有一个名为ogle的实验性调试器包。 Not sure how well it works.不确定它的效果如何。

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.内置的 print 和 println 可以工作,但是 fmt 中的函数有时会更好地工作,具体取决于您要查找的信息。

获取JetBrains Toolbox ,下载 GoLand,点击编辑器左侧的 ,它会设置一个断点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM