原创分享 Go 语言开发调试中阶

nevermosby · 2020年03月04日 · 809 次阅读
本帖已被设为精华帖!

上一篇文章给大家介绍了目前流行的 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方法打上了断点,所以主程序启动后就停在了我们设置的断点上。

下面是实际操作动图: dlv-debug

就是他干的好事,神器 delve

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

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

博客原文

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio
nevermosby GO 语言开发调试高阶 中提及了此贴 03月04日 01:30
kevin 将本帖设为了精华贴 03月04日 09:50
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册