Go 語言開發除錯中階

nevermosby發表於2020-03-04

上一篇文章給大家介紹了目前流行的 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,敬請期待。

部落格原文

更多原創文章乾貨分享,請關注公眾號
  • Go 語言開發除錯中階
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章