如何使用 dlv 调试 Golang 程序?
(给Go开发大全
加星标)
来源:Curpointer
https://zhuanlan.zhihu.com/p/126183467
【导读】golang调试工具dlv在开发工作中非常实用,怎么装、怎么用?本文带你快速上手dlv调试工具。
今早思考,在go语言的学习过程中,我们常用调试PHP的方法对某个变量进行print或者log输出,虽然这样的操作可以解决大部分的程序问题。但是,如果面对goroutine这样的调试输出,又该如何进行呢?
OK,Go给我们提供了一个非常好用的调试工具dlv(类似于gdb)。
1、delve(dlv)安装方法
dlv的具体安装方法参考:https://github.com/go-delve/delve
由于我的环境是Linux Centos环境,所以选择Linux安全,这里有两种方法,选择哪种方法都可以。
安装成功后,运行dlv命令,显示如下图所示:
2、Debug 第一个golang程序
Description:程序是从一个config.yaml文件中读取配置信息输出。
其中,config.yaml是我们的配置文件:
TimeStamp: "2018-07-16 10:23:19"
Author: "WZP"
PassWd: "Hello"
Information:
Name: "Harry"
Age: "37"
Alise:
- "Lion"
- "NK"
- "KaQS"
Image: "/path/header.rpg"
Public: false
Favorite:
Sport:
- "swimming"
- "football"
Music:
- "zui xuan min zu feng"
LuckyNumber: 99
主程序main.go文件:
package main
import (
"fmt"
"log"
"github.com/spf13/viper"
)
type config struct {
v *viper.Viper
}
func LoadConfigFromYaml(c *config) error {
c.v = viper.New()
c.v.SetConfigFile("./config.yaml")
if err := c.v.ReadInConfig(); err != nil {
return err
}
age := c.v.Get("Information.Age")
name := c.v.Get("Information.Name")
log.Printf("age:%s, name:%s\n", age, name)
m := c.v.Sub("information")
log.Printf("keys:%s, image:%s", m.AllKeys(), m.Get("image"))
return nil
}
func main() {
cfg := config{v: viper.New()}
if err := LoadConfigFromYaml(&cfg); err != nil {
fmt.Println("Failed read config")
}
}
3、启动dlv debug main.go
dlv debug main.go
Type 'help' for list of commands.
(dlv) break main.main
Breakpoint 1 set at 0x97be08 for main.main() ./main.go:30
(dlv) continue
> main.main() ./main.go:30 (hits goroutine(1):1 total:1) (PC: 0x97be08)
25: m := c.v.Sub("information")
26: log.Printf("keys:%s, image:%s", m.AllKeys(), m.Get("image"))
27: return nil
28: }
29:
=> 30: func main() {
31: cfg := config{v: viper.New()}
32: if err := LoadConfigFromYaml(&cfg); err != nil {
33: fmt.Println("Failed read config")
34: }
35: }
(dlv) break main.LoadConfigFromYaml
Breakpoint 2 set at 0x97b9eb for main.LoadConfigFromYaml() ./main.go:14
(dlv) c
> main.LoadConfigFromYaml() ./main.go:14 (hits goroutine(1):1 total:1) (PC: 0x97b9eb)
9:
10: type config struct {
11: v *viper.Viper
12: }
13:
=> 14: func LoadConfigFromYaml(c *config) error {
15: c.v = viper.New()
16: c.v.SetConfigFile("./config.yaml")
17:
18: if err := c.v.ReadInConfig(); err != nil {
19: return err
(dlv) next
> main.LoadConfigFromYaml() ./main.go:15 (PC: 0x97ba0d)
10: type config struct {
11: v *viper.Viper
12: }
13:
14: func LoadConfigFromYaml(c *config) error {
=> 15: c.v = viper.New()
16: c.v.SetConfigFile("./config.yaml")
17:
18: if err := c.v.ReadInConfig(); err != nil {
19: return err
20: }
(dlv) break 21
Breakpoint 3 set at 0x97bac4 for main.LoadConfigFromYaml() ./main.go:21
(dlv) c
> main.LoadConfigFromYaml() ./main.go:21 (hits goroutine(1):1 total:1) (PC: 0x97bac4)
16: c.v.SetConfigFile("./config.yaml")
17:
18: if err := c.v.ReadInConfig(); err != nil {
19: return err
20: }
=> 21: age := c.v.Get("Information.Age")
22: name := c.v.Get("Information.Name")
23: log.Printf("age:%s, name:%s\n", age, name)
24:
25: m := c.v.Sub("information")
26: log.Printf("keys:%s, image:%s", m.AllKeys(), m.Get("image"))
(dlv) next
> main.LoadConfigFromYaml() ./main.go:22 (PC: 0x97bb0e)
17:
18: if err := c.v.ReadInConfig(); err != nil {
19: return err
20: }
21: age := c.v.Get("Information.Age")
=> 22: name := c.v.Get("Information.Name")
23: log.Printf("age:%s, name:%s\n", age, name)
24:
25: m := c.v.Sub("information")
26: log.Printf("keys:%s, image:%s", m.AllKeys(), m.Get("image"))
27: return nil
(dlv) p age
interface {}(string) "37"
(dlv) n
> main.LoadConfigFromYaml() ./main.go:23 (PC: 0x97bb55)
18: if err := c.v.ReadInConfig(); err != nil {
19: return err
20: }
21: age := c.v.Get("Information.Age")
22: name := c.v.Get("Information.Name")
=> 23: log.Printf("age:%s, name:%s\n", age, name)
24:
25: m := c.v.Sub("information")
26: log.Printf("keys:%s, image:%s", m.AllKeys(), m.Get("image"))
27: return nil
28: }
(dlv) locals
age = interface {}(string) "37"
name = interface {}(string) "Harry"
(dlv) c
2020/04/06 14:03:29 age:37, name:Harry
2020/04/06 14:03:29 keys:[alise image public name age], image:/path/header.rpg
Process 5775 has exited with status 0
简单介绍一下,上述使用的命令:
1、dlv debug main.go #debug一个main.go程序
2、break(b)main.main #在main包里的main函数入口打断点
3、continue(c) #继续运行,直到断点处停止
4、next(n) #单步运行
5、locals #打印local variables
6、print(p) #打印一个变量或者表达式
7、restart(r) #Restart Process
以上是常用的调试命令,还有一些command,可以执行dlv help查看具体用法,本篇就到这里,Done!
- EOF -
Go 开发大全
参与维护一个非常全面的Go开源技术资源库。日常分享 Go, 云原生、k8s、Docker和微服务方面的技术文章和行业动态。
关注后获取
回复 Go 获取6万star的Go资源库
分享、点赞和在看
支持我们分享更多好文章,谢谢!