通过log库输出日志,我们可以对程序进行异常分析和问题追踪。但有时候,我也希望能有更直接的程序跟踪及定位工具能够帮助我们更方便快捷的追踪、定位问题,最直观的感觉还是使用调试器。Linux平台下,原生的C/C++程序,我们往往使用gdb进行程序调试,切换到Golang,我们同样还是可以使用gdb进行调试。同时我们还可以使用golang实现的调试器dlv进行调试。以下内容是我对gdb以及dlv使用及对比总结

准备工作

为展示整个调试过程,准备了一个演示项目GoDbg,整个目录结构如下所示

[lday@alex GoDbg]$ tree
.
├── main.go
└── mylib
    └── dbgTest.go

其中,main.go为主函数入口,而dbgTest.go启动多个goroutine,用于演示调试操作。
main.go:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main
 
import (
"GoWorks/GoDbg/mylib"
"fmt"
"os"
)
 
func main() {
fmt.Println( "Golang dbg test...")
 
var argc = len(os.Args)
var argv = append([]string{}, os.Args...)
 
fmt.Printf( "argc:%d\n", argc)
fmt.Printf( "argv:%v\n", argv)
 
var var1 = 1
var var2 = "golang dbg test"
var var3 = []int{1, 2, 3}
var var4 mylib.MyStruct
var4.A = 1
var4.B = "golang dbg my struct field B"
var4.C = map[int]string{1: "value1", 2: "value2", 3: "value3"}
var4.D = [] string{"D1", "D2", "D3"}
 
mylib.DBGTestRun(var1, var2, var3, var4)
fmt.Println( "Golang dbg test over")
}

 

dbgTest.go:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package mylib
 
import (
"fmt"
"sync"
"time"
)
 
type MyStruct struct {
A int
B string
C map[int]string
D [] string
}
 
func DBGTestRun(var1 int, var2 string, var3 []int, var4 MyStruct) {
fmt.Println( "DBGTestRun Begin!\n")
waiter := &sync.WaitGroup{}
 
waiter.Add( 1)
go RunFunc1(var1, waiter)
 
waiter.Add( 1)
go RunFunc2(var2, waiter)
 
waiter.Add( 1)
go RunFunc3(&var3, waiter)
 
waiter.Add( 1)
go RunFunc4(&var4, waiter)
 
waiter.Wait()
fmt.Println( "DBGTestRun Finished!\n")
}
 
func RunFunc1(variable int, waiter *sync.WaitGroup) {
fmt.Printf( "var1:%v\n", variable)
for {
if variable != 123456 {
continue
} else {
break
}
}
time.Sleep( 10 * time.Second)
waiter.Done()
}
 
func RunFunc2(variable string, waiter *sync.WaitGroup) {
fmt.Printf( "var2:%v\n", variable)
time.Sleep( 10 * time.Second)
waiter.Done()
}
 
func RunFunc3(pVariable *[]int, waiter *sync.WaitGroup) {
fmt.Printf( "*pVar3:%v\n", *pVariable)
time.Sleep( 10 * time.Second)
waiter.Done()
}
 
func RunFunc4(pVariable *MyStruct, waiter *sync.WaitGroup) {
fmt.Printf( "*pVar4:%v\n", *pVariable)
time.Sleep( 10 * time.Second)
waiter.Done()
}

 

-g3-gcflags="-N -l"-N -lgo build -gcflags="-N -l" GoWorks/GoDbg

gdb调试程序

因为gdb对Golang的支持也是在不断完善中,为使用gdb调试Golang程序,建议将gdb升级到相对较新版本,目前,我使用的版本是gdb7.10
大多数命令在使用gdb调试C/C++时都会用到,详细说明可参考:Debugging Go Code with GDB,具体操作如下:

[lday@alex GoDbg]$ gdb ./GoDbg
(gdb) b main.main
Breakpoint 1 at 0x401000: file /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go, line 9.
(gdb) r arg1 arg2
Starting program: /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/GoDbg arg1 arg2
[New LWP 8412]
[New LWP 8413]
[New LWP 8414]
[New LWP 8415]

Breakpoint 1, main.main () at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
9    func main() {
(gdb) b dbgTest.go:16
Breakpoint 3 at 0x457960: file /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go, line 16.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000401000 in main.main 
                                                   at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
    breakpoint already hit 1 time
2       breakpoint     keep y   0x0000000000401000 in main.main 
                                                   at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
    breakpoint already hit 1 time
3       breakpoint     keep y   0x0000000000457960 in GoWorks/GoDbg/mylib.DBGTestRun 
                                                   at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:16
(gdb) dis 1   
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x0000000000401000 in main.main 
                                                   at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
    breakpoint already hit 1 time
2       breakpoint     keep y   0x0000000000401000 in main.main 
                                                   at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
    breakpoint already hit 1 time
3       breakpoint     keep y   0x0000000000457960 in GoWorks/GoDbg/mylib.DBGTestRun 
                                                   at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:16
(gdb) del 1
(gdb) info b
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x0000000000401000 in main.main 
                                                   at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
    breakpoint already hit 1 time
3       breakpoint     keep y   0x0000000000457960 in GoWorks/GoDbg/mylib.DBGTestRun 
                                                   at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:16
(gdb) c
Continuing.
Golang dbg test...
argc:3
argv:[/home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/GoDbg arg1 arg2]

Breakpoint 3, GoWorks/GoDbg/mylib.DBGTestRun (var1=1, var2="golang dbg test")
    at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:16
16    func DBGTestRun(var1 int, var2 string, var3 []int, var4 MyStruct) {
(gdb) 
(gdb) l
11        B string
12        C map[int]string
13        D []string
14    }
15    
16    func DBGTestRun(var1 int, var2 string, var3 []int, var4 MyStruct) {
17        fmt.Println("DBGTestRun Begin!\n")
18        waiter := &sync.WaitGroup{}
19    
20        waiter.Add(1)
(gdb) n
DBGTestRun Begin!

18        waiter := &sync.WaitGroup{}
(gdb) l 17
12        C map[int]string
13        D []string
14    }
15    
16    func DBGTestRun(var1 int, var2 string, var3 []int, var4 MyStruct) {
17        fmt.Println("DBGTestRun Begin!\n")
18        waiter := &sync.WaitGroup{}
19    
20        waiter.Add(1)
21        go RunFunc1(var1, waiter)
(gdb) p var1 
$3 = 1
(gdb) p var2
$4 = "golang dbg test"
(gdb) p var3
No symbol "var3" in current context.
(gdb) bt
#0  GoWorks/GoDbg/mylib.DBGTestRun (var1=1, var2="golang dbg test")
    at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:17
#1  0x00000000004018c2 in main.main () at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:27
(gdb) f 1
#1  0x00000000004018c2 in main.main () at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:27
27        mylib.DBGTestRun(var1, var2, var3, var4)
(gdb) l
22        var4.A = 1
23        var4.B = "golang dbg my struct field B"
24        var4.C = map[int]string{1: "value1", 2: "value2", 3: "value3"}
25        var4.D = []string{"D1", "D2", "D3"}
26    
27        mylib.DBGTestRun(var1, var2, var3, var4)
28        fmt.Println("Golang dbg test over")
29    }
(gdb) print var1 
$5 = 1
(gdb) print var2
$6 = "golang dbg test"
(gdb) print var3
$7 =  []int = {1, 2, 3}

(gdb) print var4
$8 = {A = 1, B = "golang dbg my struct field B", C = map[int]string = {[1] = "value1", [2] = "value2", [3] = "value3"}, 
D =  []string = {"D1", "D2", "D3"}}
(gdb) n
23        waiter.Add(1)
(gdb) info goroutines
* 1 running  runtime.systemstack_switch
  2 waiting  runtime.gopark
  17 waiting  runtime.gopark
  18 waiting  runtime.gopark
  19 runnable GoWorks/GoDbg/mylib.RunFunc1
(gdb) goroutine 19 bt
#0  GoWorks/GoDbg/mylib.RunFunc1 (variable=1, waiter=0xc8200721f0)
    at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:36
#1  0x0000000000456df1 in runtime.goexit () at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/asm_amd64.s:1998
#2  0x0000000000000001 in ?? ()
#3  0x000000c8200721f0 in ?? ()
#4  0x0000000000000000 in ?? ()
(gdb) goroutine 19 info args
variable = 1
waiter = 0xc8200721f0
(gdb) goroutine 19 p waiter 
$1 = (struct sync.WaitGroup *) 0xc8200721f0

(gdb) goroutine 19 p *waiter 
$2 = {state1 = "\000\000\000\000\001\000\000\000\000\000\000", sema = 0}
(gdb) n
26        waiter.Add(1)
(gdb) info goroutines
* 1 running  runtime.systemstack_switch
  2 waiting  runtime.gopark
  17 waiting  runtime.gopark
  18 waiting  runtime.gopark
* 19 running  syscall.Syscall
  20 runnable GoWorks/GoDbg/mylib.RunFunc2
(gdb) goroutine 19 bt
#0  syscall.Syscall () at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/syscall/asm_linux_amd64.s:19
#1  0x00000000004ab95f in syscall.write (fd=1, p= []uint8 = {...}, n=859530587568, err=...)
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/syscall/zsyscall_linux_amd64.go:1064
#2  0x00000000004ab40d in syscall.Write (fd=5131648, p= []uint8, n=0, err=...)
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/syscall/syscall_unix.go:180
#3  0x000000000046c928 in os.(*File).write (f=0xc820084008, b= []uint8, n=4571929, err=...)
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/os/file_unix.go:255
#4  0x000000000046aa24 in os.(*File).Write (f=0xc82008a000, b= []uint8 = {...}, n=7, err=...)
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/os/file.go:144
#5  0x000000000045c707 in fmt.Fprintf (w=..., format="var1:%v\n", a= []interface {} = {...}, n=7, err=...)
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:190
#6  0x000000000045c7b4 in fmt.Printf (format="var1:%v\n", a= []interface {} = {...}, n=7, err=...)
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:197
#7  0x00000000004583eb in GoWorks/GoDbg/mylib.RunFunc1 (variable=1, waiter=0xc8200721f0)
    at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:37
#8  0x0000000000456df1 in runtime.goexit () at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/asm_amd64.s:1998
#9  0x0000000000000001 in ?? ()
#10 0x000000c8200721f0 in ?? ()
#11 0x0000000000000000 in ?? ()
(gdb) goroutine 19 f 7
#7  0x00000000004583eb in GoWorks/GoDbg/mylib.RunFunc1 (variable=1, waiter=0xc8200721f0)
    at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:37
37        fmt.Printf("var1:%v\n", variable)
Python Exception <class 'gdb.error'> Frame is invalid.: 
Error occurred in Python command: Frame is invalid.

dlv调试程序

尝试了”老牌”调试器gdb,我们再来试试新进的Golang原生调试器delve(dlv)。

Delve is a debugger for the Go programming language. The goal of the project is to provide a simple, full featured debugging tool for Go

go get github.com/derekparker/delve/cmd/dlv
[lday@alex GoDbg]$ dlv exec ./GoDbg -- arg1 arg2 
Type 'help' for list of commands.
(dlv) 
(dlv) b main.main
Breakpoint 1 set at 0x40101b for main.main() ./main.go:9
(dlv) c
> main.main() ./main.go:9 (hits goroutine(1):1 total:1) (PC: 0x40101b)
     4:        "GoWorks/GoDbg/mylib"
     5:        "fmt"
     6:        "os"
     7:    )
     8:    
=>   9:    func main() {
    10:        fmt.Println("Golang dbg test...")
    11:    
    12:        var argc = len(os.Args)
    13:        var argv = append([]string{}, os.Args...)
    14:    
(dlv) b dbgTest.go:17
Breakpoint 2 set at 0x457f51 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:17
(dlv) b dbgTest.go:23
Breakpoint 3 set at 0x4580d0 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:23
(dlv) b dbgTest.go:26
Breakpoint 4 set at 0x458123 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:26
(dlv) b dbgTest.go:29
Breakpoint 5 set at 0x458166 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:29
(dlv) bp
Breakpoint unrecovered-panic at 0x429690 for runtime.startpanic() /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/panic.go:524 (0)
Breakpoint 1 at 0x40101b for main.main() ./main.go:9 (1)
Breakpoint 2 at 0x457f51 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:17 (0)
Breakpoint 3 at 0x4580d0 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:23 (0)
Breakpoint 4 at 0x458123 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:26 (0)
Breakpoint 5 at 0x458166 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:29 (0)
(dlv) clear 5
Breakpoint 5 cleared at 0x458166 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:29
(dlv) bp
Breakpoint unrecovered-panic at 0x429690 for runtime.startpanic() /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/panic.go:524 (0)
Breakpoint 1 at 0x40101b for main.main() ./main.go:9 (1)
Breakpoint 2 at 0x457f51 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:17 (0)
Breakpoint 3 at 0x4580d0 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:23 (0)
Breakpoint 4 at 0x458123 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:26 (0)
(dlv) ls
> GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:17 (hits goroutine(1):1 total:1) (PC: 0x457f51)
    12:        C map[int]string
    13:        D []string
    14:    }
    15:    
    16:    func DBGTestRun(var1 int, var2 string, var3 []int, var4 MyStruct) {
=>  17:        fmt.Println("DBGTestRun Begin!\n")
    18:        waiter := &sync.WaitGroup{}
    19:    
    20:        waiter.Add(1)
    21:        go RunFunc1(var1, waiter)
    22:    
(dlv) bt
0  0x0000000000457f51 in GoWorks/GoDbg/mylib.DBGTestRun
   at ./mylib/dbgTest.go:17
1  0x0000000000401818 in main.main
   at ./main.go:27
2  0x000000000042aefb in runtime.main
   at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/proc.go:188
3  0x0000000000456df0 in runtime.goexit
   at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/asm_amd64.s:1998
(dlv) print var1
1
(dlv) print var2
"golang dbg test"
(dlv) print var3
[]int len: 3, cap: 3, [1,2,3]
(dlv) print var4
GoWorks/GoDbg/mylib.MyStruct {
    A: 1,
    B: "golang dbg my struct field B",
    C: map[int]string [
        1: "value1", 
        2: "value2", 
        3: "value3", 
    ],
    D: []string len: 3, cap: 3, ["D1","D2","D3"],}
(dlv) frame 1 ls
    22:        var4.A = 1
    23:        var4.B = "golang dbg my struct field B"
    24:        var4.C = map[int]string{1: "value1", 2: "value2", 3: "value3"}
    25:        var4.D = []string{"D1", "D2", "D3"}
    26:    
=>  27:        mylib.DBGTestRun(var1, var2, var3, var4)
    28:        fmt.Println("Golang dbg test over")
    29:    }
(dlv) 
> GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:26 (hits goroutine(1):1 total:1) (PC: 0x458123)
    21:        go RunFunc1(var1, waiter)
    22:    
    23:        waiter.Add(1)
    24:        go RunFunc2(var2, waiter)
    25:    
=>  26:        waiter.Add(1)
    27:        go RunFunc3(&var3, waiter)
    28:    
    29:        waiter.Add(1)
    30:        go RunFunc4(&var4, waiter)
    31:    
(dlv) goroutines
[6 goroutines]
* Goroutine 1 - User: ./mylib/dbgTest.go:26 GoWorks/GoDbg/mylib.DBGTestRun (0x458123) (thread 9022)
  Goroutine 2 - User: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/proc.go:263 runtime.gopark (0x42b2d3)
  Goroutine 3 - User: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/proc.go:263 runtime.gopark (0x42b2d3)
  Goroutine 4 - User: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/proc.go:263 runtime.gopark (0x42b2d3)
  Goroutine 5 - User: ./mylib/dbgTest.go:39 GoWorks/GoDbg/mylib.RunFunc1 (0x4583eb) (thread 9035)
  Goroutine 6 - User: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/format.go:130 fmt.(*fmt).padString (0x459545)
(dlv) goroutine 6
Switched from 1 to 6 (thread 9022)
(dlv) bt
 0  0x0000000000454730 in runtime.systemstack_switch
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/asm_amd64.s:245
 1  0x000000000040f700 in runtime.mallocgc
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/malloc.go:643
 2  0x000000000040fc43 in runtime.rawmem
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/malloc.go:809
 3  0x000000000043c2a5 in runtime.growslice
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/slice.go:95
 4  0x000000000043c015 in runtime.growslice_n
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/slice.go:44
 5  0x0000000000459545 in fmt.(*fmt).padString
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/format.go:130
 6  0x000000000045a13f in fmt.(*fmt).fmt_s
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/format.go:322
 7  0x000000000045e905 in fmt.(*pp).fmtString
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:518
 8  0x000000000046200f in fmt.(*pp).printArg
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:797
 9  0x0000000000468a8d in fmt.(*pp).doPrintf
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:1238
10  0x000000000045c654 in fmt.Fprintf
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:188
(dlv) bt 13
...
10  0x000000000045c654 in fmt.Fprintf
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:188
11  0x000000000045c74b in fmt.Printf
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:197
12  0x000000000045846f in GoWorks/GoDbg/mylib.RunFunc2
    at ./mylib/dbgTest.go:50
13  0x0000000000456df0 in runtime.goexit
    at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/asm_amd64.s:1998
(dlv) frame 12 ls
    45:        time.Sleep(10 * time.Second)
    46:        waiter.Done()
    47:    }
    48:    
    49:    func RunFunc2(variable string, waiter *sync.WaitGroup) {
=>  50:        fmt.Printf("var2:%v\n", variable)
    51:        time.Sleep(10 * time.Second)
    52:        waiter.Done()
    53:    }
    54:    
    55:    func RunFunc3(pVariable *[]int, waiter *sync.WaitGroup) {
(dlv) frame 12 print variable 
"golang dbg test"
(dlv) frame 12 print waiter
*sync.WaitGroup {
    state1: [12]uint8 [0,0,0,0,2,0,0,0,0,0,0,0],
    sema: 0,}
(dlv) goroutine
Thread 9022 at ./mylib/dbgTest.go:26
Goroutine 6:
    Runtime: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/asm_amd64.s:245 runtime.systemstack_switch (0x454730)
    User: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/format.go:130 fmt.(*fmt).padString (0x459545)
    Go: ./mylib/dbgTest.go:26 GoWorks/GoDbg/mylib.DBGTestRun (0x458123)

dlv前端(gdlv)

dlv提供了类似gdb的cli调试系统,而有第三方还提供了dlv的GUI前端(gdlv),对于那些习惯了使用GUI进行调试的人来说,结合gdlv和dlv,调试会更加方便。gdlv有个问题是:他无法在xwindows server上运行,只能在server本地运行。

结论

综合比较两个Golang程序调试器gdb和dlv,我认为dlv的功能更为完善,更能满足实际调试时的功能需求。两者的优缺点比较大致如下

 
调试器优势不足
dlv对goroutine环境调试支持比较完善暂时没找到
gdb符合现有的调试习惯,类似C/C++调试指令都有对goroutine场景支持不足,不能很好的应对goroutine的调试