使用dlv调试golang程序

使用dlv调试golang程序1 编译选项 gobuild gcflags all N l 必须这样编译 才能用 gdb 打印出变量 第二个是小写的 L 不是大写的 i 需要加编译选项 类似 gcc 中的 g 选项 加入调试信息 关于如何安装 dlv 请自行百度或者谷歌 2 使用 dlv 调试 dlv 的功能介绍 Usage dlv command AvailableCom attach

1、编译选项

go build -gcflags=all="-N -l"  必须这样编译,才能用gdb打印出变量,第二个是小写的L,不是大写的i 

需要加编译选项,类似gcc中的 -g选项,加入调试信息。关于如何安装dlv,请自行百度或者谷歌。

2、使用dlv调试

dlv的功能介绍

Usage: dlv [command] Available Commands: attach Attach to running process and begin debugging. connect Connect to a headless debug server. core Examine a core dump. debug Compile and begin debugging main package in current directory, or the package specified. exec Execute a precompiled binary, and begin a debug session. help Help about any command run Deprecated command. Use 'debug' instead. test Compile test binary and begin debugging program. trace Compile and begin tracing program. version Prints version. 

由于dlv的功能比较多,我只介绍我常用的几个,包括 attach、debug、exec、core、test,这5个。

1、dlv attach

这个相当于gdb -p 或者 gdb attach ,即跟踪一个正在运行的程序。这中用法也是很常见,对于一个后台程序,它已经运行很久了,此时你需要查看程序内部的一些状态,只能借助attach.

dlv attach $PID  后面的进程的ID 

2、dlv debug

dlv debug main/hundredwar.go  先编译,后启动调试  

3、dlv exec

dlv exec ./HundredsServer  直接启动调试 dlv exec ./HundredsServer -- -port 8888 -c /home/config.xml  后面加参数启动调试 

与dlv debug区别就是,dlv debug 编译一个临时可执行文件,然后启动调试,类似与go run。

4、dlv core

用来调试core文件,但是想让go程序生成core文件,需要配置一个环境变量,默认go程序不会产生core文件。

export GOTRACEBACK=crash 

只有定义这个环境变量,go程序才会coredump。如果在协程入口定义defer函数,然后recover也不会产生core文件。

go func() { 
    defer func() { 
    if r := recover(); r != nil { 
    fmt.Printf("panic error\n") } }() var p *int = nil fmt.Printf("p=%d\n", *p) // 访问nil指责 }() // 这个协程不会生产core文件 

因为recover的作用就是捕获异常,然后进行错误处理,所以不会产生coredump,这个需要注意。这个也是golang的一大特色吧,捕获异常,避免程序coredump。

调试coredump文件

关于调试core文件,其实和C/C++差不多,最后都是找到发生的函数帧,定位到具体某一行代码。但是golang稍有不同,对于golang的core文件需要先定位到时哪一个goroutine发生了异常。

dlv core ./Server core.26945  启动 
Type 'help' for list of commands. (dlv) goroutines  查看所有goroutine [12 goroutines] Goroutine 1 - User: /usr/local/go/src/runtime/time.go:102 time.Sleep (0x440d16) Goroutine 2 - User: /usr/local/go/src/runtime/proc.go:292 runtime.gopark (0x42834a) Goroutine 3 - User: /usr/local/go/src/runtime/proc.go:292 runtime.gopark (0x42834a) Goroutine 4 - User: /usr/local/go/src/runtime/proc.go:292 runtime.gopark (0x42834a) Goroutine 5 - User: /usr/local/go/src/runtime/time.go:102 time.Sleep (0x440d16) Goroutine 6 - User: /usr/local/go/src/runtime/time.go:102 time.Sleep (0x440d16) Goroutine 7 - User: /usr/local/go/src/runtime/time.go:100 time.Sleep (0x440ccd) Goroutine 8 - User: ./time.go:114 main.main.func2 (0x4a33cb) (thread 21239) Goroutine 9 - User: /usr/local/go/src/runtime/lock_futex.go:227 runtime.notetsleepg (0x40ce42) Goroutine 17 - User: /usr/local/go/src/runtime/proc.go:292 runtime.gopark (0x42834a) Goroutine 33 - User: /usr/local/go/src/runtime/proc.go:292 runtime.gopark (0x42834a) Goroutine 49 - User: /usr/local/go/src/runtime/proc.go:292 runtime.gopark (0x42834a) 

上面,可以看到所以的goroutine,需要找到自己的业务代码所在的goroutine,这里需要判断,不像C/C++的core文件,可以定义定位到所在的函数栈。这里的是 Goroutine 8 。

需要进入 8 号 goroutine。

(dlv) goroutine 8  切换到 8 号 goroutine Switched from 0 to 8 (thread 21239) 
(dlv) bt  查看栈帧 0 0x0000000000 in runtime.raise at /usr/local/go/src/runtime/sys_linux_amd64.s:159 1 0x000000000044cea0 in runtime.systemstack_switch at /usr/local/go/src/runtime/asm_amd64.s:363 2 0x00000000004265ba in runtime.dopanic at /usr/local/go/src/runtime/panic.go:597 3 0x00000000004261f1 in runtime.gopanic at /usr/local/go/src/runtime/panic.go:551 4 0x00000000004250ce in runtime.panicmem at /usr/local/go/src/runtime/panic.go:63 5 0x0000000000438baa in runtime.sigpanic at /usr/local/go/src/runtime/signal_unix.go:388 6 0x00000000004a33cb in main.main.func2 at ./time.go:114  显然6号栈是自己的业务代码 7 0x000000000044f6d1 in runtime.goexit at /usr/local/go/src/runtime/asm_amd64.s:2361 
(dlv) frame 6  进入6号栈帧 > runtime.raise() /usr/local/go/src/runtime/sys_linux_amd64.s:159 (PC: 0x) Warning: debugging optimized function Frame 6: ./time.go:114 (PC: 4a33cb) 109: // if r := recover(); r != nil { 
    110: 111: // } 112: // }() 113: var p *int = nil => 114: fmt.Printf("p=%d\n", *p)  这里发生了异常 115: }() 116: 117: time.Sleep() 118: } 

5、dlv test

dlv test 也很有特色,是用来调试测试代码的。因为测试代码都是某一个包里面,是以包为单位的。

dlv test $packname  包名 
[KentZhang@LOCAL-192-168-97-2 src]$ dlv test db  调试db包内部的测试用例 Type 'help' for list of commands. (dlv) b TestMoneyDbGet  打断点,不用加包名了 Breakpoint 1 set at 0x73c15b for db.TestMoneyDbGet() ./db/moneydb_test.go:9 (dlv) c > db.TestMoneyDbGet() ./db/moneydb_test.go:9 (hits goroutine(5):1 total:1) (PC: 0x73c15b) 4: "logger" 5: "testing" 6: ) 7: 8: //日志不分离 => 9: func TestMoneyDbGet(t *testing.T) { 
    10: logger.Init("testlog", ".", 1000, 3, logger.DEBUG_LEVEL, false, logger.PUT_CONSOLE) 11: c := MoneydbConnect("192.168.202.92:12515") 12: if nil == c { 
    13: t.Error("Init() failed.") 14: return (dlv) 

3、调试命令

关于dlv内的调试命令,和gdb差不多,可以使用help查看所有命令。

help

(dlv) help The following commands are available: args -------------------------------- Print function arguments. break (alias: b) -------------------- Sets a breakpoint. breakpoints (alias: bp) ------------- Print out info for active breakpoints. call -------------------------------- Resumes process, injecting a function call (EXPERIMENTAL!!!) check (alias: checkpoint) ----------- Creates a checkpoint at the current position. checkpoints ------------------------- Print out info for existing checkpoints. clear ------------------------------- Deletes breakpoint. clear-checkpoint (alias: clearcheck) Deletes checkpoint. clearall ---------------------------- Deletes multiple breakpoints. condition (alias: cond) ------------- Set breakpoint condition. config ------------------------------ Changes configuration parameters. continue (alias: c) ----------------- Run until breakpoint or program termination. disassemble (alias: disass) --------- Disassembler. down -------------------------------- Move the current frame down. edit (alias: ed) -------------------- Open where you are in $DELVE_EDITOR or $EDITOR exit (alias: quit | q) -------------- Exit the debugger. frame ------------------------------- Set the current frame, or execute command on a different frame. funcs ------------------------------- Print list of functions. goroutine --------------------------- Shows or changes current goroutine goroutines -------------------------- List program goroutines. help (alias: h) --------------------- Prints the help message. list (alias: ls | l) ---------------- Show source code. locals ------------------------------ Print local variables. next (alias: n) --------------------- Step over to next source line. on ---------------------------------- Executes a command when a breakpoint is hit. print (alias: p) -------------------- Evaluate an expression. regs -------------------------------- Print contents of CPU registers. restart (alias: r) ------------------ Restart process from a checkpoint or event. rewind (alias: rw) ------------------ Run backwards until breakpoint or program termination. set --------------------------------- Changes the value of a variable. source ------------------------------ Executes a file containing a list of delve commands sources ----------------------------- Print list of source files. stack (alias: bt) ------------------- Print stack trace. step (alias: s) --------------------- Single step through program. step-instruction (alias: si) -------- Single step a single cpu instruction. stepout ----------------------------- Step out of the current function. thread (alias: tr) ------------------ Switch to the specified thread. threads ----------------------------- Print out info for every traced thread. trace (alias: t) -------------------- Set tracepoint. types ------------------------------- Print list of types up ---------------------------------- Move the current frame up. vars -------------------------------- Print package variables. whatis ------------------------------ Prints type of an expression. 

help [command]

使用 help command 打印出具体命令的用法,例如:

(dlv) help set Changes the value of a variable. [goroutine <n>] [frame <m>] set <variable> = <value> (dlv) help on Executes a command when a breakpoint is hit. on <breakpoint name or id> <command>. 

4、config

(dlv) config -list aliases map[] substitute-path [] max-string-len <not defined> max-array-values <not defined> max-variable-recurse <not defined> show-location-expr false source-list-line-color 34 debug-info-directories [/usr/lib/debug/.build-id] 

使用p打较长的字符串时,会显示不全,需要配置更长的长度:

(dlv) config max-string-len 99999 

5、修改变量值

set num = 1  这种修改string变量的,必须使用 call , set 不行  call ctx.Setting.Password = "gQx%7TUB#1cF"  call 其实调用函数 call len(arr) 

6、dlv的不足之处

dlv和gdb相比,除了支持协程这一优势之外,其他的地方远不如gdb。比如

  • dlv 的print 不支持十六进制打印,gdb就可以,p /x number
  • dlv不支持变量、函数名的自动补全
  • dlv的on 功能与gdb的commands类似,可惜的是dlv只支持print, stack and goroutine三个命令,竟然不支持continue

还有一个特殊情况,如果一个函数有定义,但是没在任何地方调用,那么dlv打断点打不到

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/198232.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午3:31
下一篇 2026年3月26日 下午3:31


相关推荐

  • 数据挖掘十大算法之决策树详解(1)[通俗易懂]

    数据挖掘十大算法之决策树详解(1)[通俗易懂]在2006年12月召开的IEEE数据挖掘国际会议上,与会的各位专家选出了当时的十大数据挖掘算法(top10dataminingalgorithms)。本博客已经介绍过的位列十大算法之中的5个。本文主要介绍机器学习中的决策树模型。决策树模型是一类算法的集合,在数据挖掘十大算法中,具体的决策树算法占有两席位置,即C4.5和CART算法

    2022年6月1日
    42
  • (二)边界值分析法

    (二)边界值分析法1 定义 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法 通常边界值分析法是作为对等价类划分法的补充 这种情况下 其测试用例来自等价类的边界 根据大量的测试统计数据 很多错误是发生在输入或输出范围的边界上 而不是发生在输入 输出范围的中间区域 因此针对各种边界情况设计测试用例 可以查出更多的错误 使用边界值分析方法设计测试用例 首先应确定边界情况 通常输入和输出等价类的边界

    2026年3月19日
    2
  • 蓝桥杯历届真题题目+解析+代码+答案(2013-2020)(JavaA、B、C组)(C++语言)(Python)

    蓝桥杯历届真题题目+解析+代码+答案(2013-2020)(JavaA、B、C组)(C++语言)(Python)题目及题解持续更新中 2020 年第十一届省赛 Java 组 题目 题解题目序号 Java A 组 Java B 组 Java C 组题目类型分值题目 1 结果填空 5 题目 2 结果填空 5 题目 3 结果填空 10 题目 4 结果填空 10 题目 5 结果填空 15 题目 6 编程大题 15 题目 7 编程大题 20 题目 8 结果填空 20 题目 9 编程大题 25 题目 10 编程大题年第十

    2026年3月17日
    2
  • 来自damon的zencart二次开发教程-3.2复制模板(仿站)操作教程「建议收藏」

    来自damon的zencart二次开发教程-3.2复制模板(仿站)操作教程「建议收藏」用zencart来复制别人的网站成本低,效率高。前面我发了一篇有关开发自己的zencat模板的文章(《来自damon的zencart二次开发教程-3.1开发自己的zencart模板》),里面只有一些基础的理论,下面,我们就来实际操作一下。1.利用离线浏览器将(《离线浏览器Teleport_Pro完全教程与安装文件下载》)你的目标网页文件(图片,html以及css样式表,j…

    2025年10月2日
    2
  • dede添加会员功能听语音

    dede添加会员功能听语音

    2021年9月25日
    49
  • [弗曼学习法] Study for learning methods

    [弗曼学习法] Study for learning methods第一步 -选择一个你想要理解的概念    选择一个你想要理解的概念, 然后拿出一张白纸, 把这个概念写在白纸的最上边.第二步-设想一种场景,你正要向别人传授这个概念    在白纸上写下你对这个概念的解释, 就好像你正在教导一位新接触这个概念的学生一样. 当你这样做的时候, 你会更清楚地意识到关于这个概念你理解了多少, 以及是否还存在理解不清的地方.第三步-如果你感觉卡壳了…

    2022年6月12日
    48

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号