注:本文做者是 YANN,原文是 Introduction to Go Debugging with GDBhtml
在過去的 4 年中,我花了我絕大部分的時間用來寫,讀以及調試 Python 或 JavaScript 代碼。在學習 Go 的過程當中,像穿着一雙有小石子的鞋子在美麗的山中遠行。不少事情給我留下了深入的印象,可是使用 println
調試個人代碼在過去走的太遠了。在 Python 中,當代碼在運行的時候,咱們使用 pdb/ipdb
調試它,JavaScript 提供了相似的工具。在這些年中,這個模式已經變成了我工做流中很是重要的一部分了。golang
今天,我認識到 Go 已經內建支持 Gnu debugger (aka GDB)。express
爲了這篇文章,咱們使用如下這個簡單的程序:ubuntu
package main import ( "fmt" "time" ) func counting(c chan<- int) { for i := 0; i < 10; i++ { time.Sleep(2 * time.Second) c <- i } close(c) } func main() { msg := "Starting main" fmt.Println(msg) bus := make(chan int) msg = "starting a gofunc" go counting(bus) for count := range bus { fmt.Println("count:", count) } }
爲了使用 GDB,你須要使用 -gcflags 」-N -l」
選項編譯你的程序,這些選項阻止編譯器使用內聯函數和變量。函數
go build -gcflags "-N -l" gdbsandbox.go
這是一個交互式的調試 GDB 的會話示例:工具
yml@simba$ gdb gdbsandbox GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04 Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
首先,咱們運行咱們的程序:oop
(gdb) run Starting program: /home/yml/Developments/go/src/gdbsandbox/gdbsandbox Starting main count: 0 count: 1 count: 2 [...] count: 9 [Inferior 1 (process 13507) exited normally]
如今咱們知道怎樣運行咱們的程序,咱們可能想設置一個斷點。學習
(gdb) help break Set breakpoint at specified line or function. break [LOCATION] [thread THREADNUM] [if CONDITION] LOCATION may be a line number, function name, or "*" and an address. [...] (gdb) break 22 Breakpoint 1 at 0x400d7a: file /home/yml/Developments/go/src/gdbsandbox/gdbsandbox.go, line 22. (gdb) run Starting program: /home/yml/Developments/go/src/gdbsandbox/gdbsandbox Starting main [New LWP 13672] [Switching to LWP 13672] Breakpoint 1, main.main () at /home/yml/Developments/go/src/gdbsandbox/gdbsandbox.go:22 22 for count := range bus { (gdb)
一旦 GDB 在你的斷點處中止,你將看到上下文:ui
(gdb) help list List specified function or line. With no argument, lists ten more lines after or around previous listing. "list -" lists the ten lines before a previous ten-line listing. [...] (gdb) list 17 msg := "Starting main" 18 fmt.Println(msg) 19 bus := make(chan int) 20 msg = "starting a gofunc" 21 go counting(bus) 22 for count := range bus { 23 fmt.Println("count:", count) 24 } 25 }
你也能夠檢查變量:debug
(gdb) help print Print value of expression EXP. Variables accessible are those of the lexical environment of the selected stack frame, plus all those whose scope is global or an entire file. [...] (gdb) print msg $1 = "starting a gofunc"
在代碼的早期,咱們啓動了一個 goroutine
,當我執行到第 10 行的時候,我想查看我程序中的這部分。
(gdb) break 10 Breakpoint 3 at 0x400c28: file /home/yml/Developments/go/src/gdbsandbox/gdbsandbox.go, line 10. (gdb) help continue Continue program being debugged, after signal or breakpoint. If proceeding from breakpoint, a number N may be used as an argument, which means to set the ignore count of that breakpoint to N - 1 (so that the breakpoint won't break until the Nth time it is reached). [...] (gdb) continue Continuing.
在今天咱們要作的最後一件事情就是在運行期改變一個變量的值:
Breakpoint 3, main.counting (c=0xf840001a50) at /home/yml/Developments/go/src/gdbsandbox/gdbsandbox.go:10 10 time.Sleep(2 * time.Second) (gdb) help whatis Print data type of expression EXP. Only one level of typedefs is unrolled. See also "ptype". (gdb) whatis count type = int (gdb) print count $3 = 1 (gdb) set variable count=3 (gdb) print count $4 = 3 (gdb) c Continuing. count: 3
咱們僅僅覆蓋瞭如下命令:
這幾乎只是涉及到了使用 GDB 的表面知識,若是你想學習關於 GDB 更多的知識,這裏有更多的連接: