上一篇文章给大家介绍了目前流行的Go语言开发IDE及其调试方式,这次给喜欢用命令行掌控一切的童鞋,介绍Go语言如何使用命令行调试开发。

DIY纯命令行调试

几年前,为学习某个开发框架,需要在系统层装一大堆的类库和脚手架(看到nodejs开发者默默点头了),搞得系统越来越臃肿。。。上帝说要有光,于是以docker为代表的容器技术诞生了,通过DIY构建镜像,能够将所有的依赖打包到一起,并且可以到处运行,一切似乎都变得简单了。。。

我们期望的镜像,要能够运行和调试Go应用程序,因此需要的依赖包括:

  • go语言安装包,直接可以从官网curl下来安装
  • gcc、gdb等系统层辅助工具,gdb其实是个大神器,我们这次不展开讨论了
  • delve安装包,被称为Go语言debugger利器,是我们能使用命令行进行调试的最重要工具,没有之一。(有兴趣的童鞋,可以去这里看看该工具作者自己的教学视频)

明确了安装依赖后,就可以动手写Dockerfile构建镜像了,可以参照我写好的Dockerfile,里面指定安装了所有依赖并已经设置好GOPATH路径。如果还嫌麻烦,就直接拉取已经构建好的镜像(docker pull robolwq/golang-debug:1.10.3)即可。

开始我们的表演

推荐大家用vagrant创建linux box来做各种test,这个box可以预装很多包括docker在内的必要服务,这样可以快速进行开发测试,并且不会污染主机环境。

准备好一段Go代码,这边选取的是一个简单的http服务:

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
    log.Println("Bite me")
}

func main() {
    http.HandleFunc("/", handler)
    log.Println("Started!!!")
    log.Fatal(http.ListenAndServe(":80", nil))
}

接下来运行以下命令:

# 启动用于调试的容器,并把目标代码目录挂载到容器内
# 特别注意这个参数“--security-opt seccomp:unconfined”
# 它的作用是禁用Linux内核层面的Secure computing mode
# 目的是为了能够正确使用dlv相关命令
# 具体可以参见:https://docs.docker.com/engine/security/seccomp/
> docker container run -ti --rm --security-opt seccomp:unconfined --net=host -v /home/vagrant/gop:/root/go robolwq/golang-debug:1.10.3  bash

# 输入 go env 验证容器内Go语言环境的有效性
> go env
# 输入 dlv 验证容器内调试工具的有效性
> dlv
Delve is a source level debugger for Go programs.
......
Pass flags to the program you are debugging using `--`, for example:

`dlv exec ./hello -- server --config conf/config.toml`

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 debug ./src/github.com/nevermosby/go-debug/main.go
Type 'help' for list of commands.
# 对main包中的main方法打上断点(breakpoint)
> (dlv) b main.main
Breakpoint 1 set at 0x7bce78 for main.main() ./src/github.com/nevermosby/go-debug/main.go:43
# 对main包中的handler方法打上断点(breakpoint)
> (dlv) b main.handler
Breakpoint 2 set at 0x7bcc48 for main.handler() ./src/github.com/nevermosby/go-debug/main.go:38
# 输入字母c,启动主程序
> (dlv) c
# 由于我们为main方法打上了断点,所以主程序启动后就停在了我们设置的断点上。

下面是实际操作动图:

就是他干的好事,神器delve

上一篇文章提到的goland、liteide、vs code这些IDE实际上都是基于神器delve实现本地开发调试。它是由Redhat大神Derek Parker创建的,可以去github关注他哦。delve本身是用go语言开发,通过RPC调用实现对目标程序的拦截和消息传递,下面是它的简易架构图,有兴趣的童鞋,可以去官方github地址研究:

与其功能类似的是gdb工具,可以通过他们的功能输出看到二者不同之处:

以上就是本次“中阶”调试文章,下一回我们再一次进阶,高阶调试——远程调试,AKA,Remote Debugging,敬请期待。

2 对 “Go语言开发调试中阶”的想法;

发表评论

电子邮件地址不会被公开。 必填项已用*标注