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

时间:2010-08-03 20:55:37

标签: debugging go

如何调试Go程序?我一直在使用Gedit Go IDE,但它没有调试。有没有办法通过我的代码和检查内存?还是我坚持打印报表?我可以使用OutputDebugString吗?

8 个答案:

答案 0 :(得分:22)

更新Debugging Go Code with GDB上的文档中现在有一个官方页面。自写这篇答案以来,已经发生了很大变化,下面列出的一些限制已被删除。我将剩余的答案留给后代,但如果你想调试Go代码,请点击上面的链接。

Go链接器now emit DWARF调试符号,可由gdb版本7.x解释。

从上面链接的博文中突出显示:

你可以......

  • 在GDB版本7.x中加载Go程序
  • 按行列出所有Go,C和汇编源文件(Go运行时的部分内容用C和汇编语言编写),
  • 按行设置断点并逐步执行代码
  • 打印堆栈跟踪并检查堆栈帧,
  • 找到地址并打印大多数变量的内容。

仍有一些不便之处:

  • Mac OS X附带的GDB版本6.x无法读取发出的DWARF代码。我们很乐意接受修补程序以使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进行检查。

答案 1 :(得分:13)

新计划(2014年5月开始):derekparker/delve

  

Delve是一个 Go调试器,用Go编写   (主要针对Linux,OsX支持即将到来,Windows支持 unknown supported in 2016

功能

  
      
  • 附加到已在运行的流程
  •   
  • 启动流程并开始调试会话
  •   
  • 设置断点,单步,跳过函数,打印变量内容
  •   

用法

  

调试器可以通过三种方式启动:

     

一步编译,运行和附加:

$ dlv -run
  

提供要调试的程序的名称,调试器将为您启动它。

$ dlv -proc path/to/program
  

提供当前正在运行的进程的pid,调试器将附加并开始会话。

$ sudo dlv -pid 44839

断点

  

Delve可以在调试会话中通过断点命令插入断点,但是为了便于调试,您还可以调用runtime.Breakpoint(),Delve将处理断点并在下一个源代码行停止程序。

答案 2 :(得分:9)

进行调试会话的另一项举措:hopwatch

  

与大多数调试器不同,hopwatch要求您在程序中的兴趣点插入函数调用。在这些程序位置,您可以告诉Hopwatch显示变量值并暂停程序(或goroutine)   Hopwatch使用Websockets在程序和HTML5页面中运行的调试器之间交换命令。

(所以它仍然类似于“打印声明”,但更优雅地查看结果而不会污染stdoutstderr

hopwatch

  

当程序调用Break函数时,它会将调试信息发送到浏览器页面并等待用户交互   使用DisplayPrintfDumpgo-spew)功能,您可以在浏览器页面上记录信息。
  在hopwatch页面上,开发人员可以查看调试信息并选择继续执行程序。

with source

答案 3 :(得分: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.go8l -o silly silly.8后,我可以运行gdb silly。 (据我所知,我有“GNU gdb(Ubuntu / Linaro 7.2-1ubuntu11)7.2”,Ubuntu 11.04 32位。)

然后我可以输入listb 7break 7的缩写)和run。它停在第7行,我可以运行:

(gdb) p foo
$1 = 5

看看Eclipse / CDT调试器和/或DDD是否适用于Go会很有趣。

答案 4 :(得分:4)

GDB 7.5正式支持Go。

答案 5 :(得分:3)

有一个名为ogle的实验性调试程序包。不确定它的效果如何。

答案 6 :(得分:3)

这很不幸,但现在最好的方法是使用打印功能。内置的print和println可以工作,但fmt中的功能有时会更好,具体取决于你所追求的信息。

答案 7 :(得分:3)

正在开发的另一种调试技术(2014年第4季度):Go Execution Tracer

  

跟踪包含

     
      
  • 与goroutine计划相关的事件:      
        
    • goroutine开始在处理器上执行,
    •   
    • 同步原语上的goroutine块,
    •   
    • goroutine创建或解除另一个goroutine;
    •   
  •   
  • 与网络相关的活动:      
        
    • 网络IO上的goroutine块,
    •   
    • goroutine在网络IO上被解锁;
    •   
  •   
  • 系统调用相关事件:      
        
    • goroutine进入系统调用,
    •   
    • 从系统调用返回goroutine;
    •   
  •   
  • 垃圾收集器相关事件:      
        
    • GC启动/停止,
    •   
    • 并发扫描开始/停止;和
    •   
  •   
  • 用户事件
  •   
     

“处理器”是指逻辑处理器,单位为GOMAXPROCS   每个事件包含事件ID,精确时间戳,OS线程ID,处理器ID,goroutine id,堆栈跟踪和其他相关信息(例如,未阻止的goroutine id)。

https://lh5.googleusercontent.com/w0znUT_0_xbipG_UlQE5Uc4PbC8Mw1duHRLg_AKTOS4iS6emOD6jnQvSDACybOfCbuSqr2ulkxULXGOBQpZ2IejPHW_8NHufqmn8q5u-fF_MSMCEgu6FwLNtMvowbq74nA