這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
註:本文作者是 YANN,原文是 Introduction to Go Debugging with GDB
在過去的 4 年中,我花了我絕大部分的時間用來寫,讀以及調試 Python 或 JavaScript 代碼。在學習 Go 的過程中,像穿著一雙有小石子的鞋子在美麗的山中遠行。很多事情給我留下了深刻的印象,但是使用 println
調試My Code在過去走的太遠了。在 Python 中,當代碼在啟動並執行時候,我們使用 pdb/ipdb
調試它,JavaScript 提供了類似的工具。在這些年中,這個模式已經變成了我工作流程中非常重要的一部分了。
今天,我認識到 Go 已經內建支援 Gnu debugger (aka GDB)。
為了這篇文章,我們使用以下這個簡單的程式:
package mainimport ( "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.04Copyright (C) 2012 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
首先,我們運行我們的程式:
(gdb) runStarting program: /home/yml/Developments/go/src/gdbsandbox/gdbsandbox Starting maincount: 0count: 1count: 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 22Breakpoint 1 at 0x400d7a: file /home/yml/Developments/go/src/gdbsandbox/gdbsandbox.go, line 22.(gdb) runStarting 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:2222 for count := range bus {(gdb)
一旦 GDB 在你的斷點處停止,你將看到上下文:
(gdb) help listList 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) list17 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 }
你也可以檢查變數:
(gdb) help printPrint value of expression EXP.Variables accessible are those of the lexical environment of the selectedstack frame, plus all those whose scope is global or an entire file.[...](gdb) print msg$1 = "starting a gofunc"
在代碼的早期,我們啟動了一個 goroutine
,當我執行到第 10 行的時候,我想查看我程式中的這部分。
(gdb) break 10Breakpoint 3 at 0x400c28: file /home/yml/Developments/go/src/gdbsandbox/gdbsandbox.go, line 10.(gdb) help continueContinue 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 thatthe breakpoint won't break until the Nth time it is reached).[...](gdb) continueContinuing.
在今天我們要做的最後一件事情就是在運行期改變一個變數的值:
Breakpoint 3, main.counting (c=0xf840001a50) at /home/yml/Developments/go/src/gdbsandbox/gdbsandbox.go:1010 time.Sleep(2 * time.Second)(gdb) help whatisPrint data type of expression EXP.Only one level of typedefs is unrolled. See also "ptype".(gdb) whatis counttype = int(gdb) print count$3 = 1(gdb) set variable count=3(gdb) print count$4 = 3(gdb) cContinuing.count: 3
我們僅僅覆蓋了以下命令:
- list
- next
- print
- continue
- break
- whatis
- set variable =
這幾乎只是涉及到了使用 GDB 的表面知識,如果你想學習關於 GDB 更多的知識,這裡有更多的連結:
- http://sourceware.org/gdb/current/onlinedocs/gdb/
- http://golang.org/doc/gdb