go runtime debug 小技巧

go-coder發表於2020-09-20

來自公眾號:新世界雜貨鋪

前言

本意是打算研究一下 go 程式的啟動流程,然後就去網上搜尋了一下入門教程。結果令我有點沮喪,搜到的幾乎所有文章開篇都是通過GDB除錯, 然後就是不同平臺下的彙編程式碼。。。

這令我很不開心, 雖然 C/C++ 應用很廣泛, 但是我對它真的沒啥興趣啊, 對它相關的除錯工具就更加不感冒了, 雖然它可以除錯 go 程式, 但是總感覺心裡少了點什麼, 難道dlv它不香嘛, 於是就有了今天這篇文章

dlv 命令列 debug

dlv 的名頭應該不用我多說, 所以我們直奔主題

  1. 開始 debug
dlv debug test.go

執行上述命令後, 就會進入 debug 互動命令列介面, 在這個介面任何時候輸入h都會列印幫助資訊.

  1. 增加函式斷點
# 互動介面輸入下面命令後, 會在main包下的main函式打上一個斷點
b main.main
  1. 指定行斷點
# 在test.go的檔案第6行打上一個斷點
b test.go:6
  1. 開始執行

如上圖所示, 我們繼續執行時會發現=>會停留在我們前面標記的斷點處。這裡的其他命令我們在本篇文章不做過多的介紹了, 我們儘量緊扣本篇的主題。

  1. 列印呼叫棧

go runtime debug 小技巧

如上圖所示, 我們通過 dlv 的呼叫棧可以看見呼叫 main 函式之前,還執行了 asm_amd64.s(本次 debug 的機器為 mac) 的彙編程式碼和 proc.go 的 main 函式。

意外之喜, 本來只是單純的不想用 GDB 除錯去了解 go 程式的啟動流程, 現在卻也有了一些頭緒, 下面我們繼續本篇的主題

  1. 在 runtime 包中標記斷點並開始除錯

綜上: 按照上面的步驟, 我們通過 dlv 就可以進行 runtiime 的除錯, 並且還可以瞭解 go 程式的啟動流程

vscode 圖形化 debug

我個人比較喜歡用 vscode 進行程式碼編輯, 所以在擼 go 的時候用的也是 vscode, 體驗還是非常不錯的

關於 vscode 如何配置 go 的開發環境和配置圖形化 debug 就不再本篇過多贅述, 筆者在這裡分享一下自己在 vscode 中關於 go 的配置

"go.useLanguageServer": true,
"go.languageServerExperimentalFeatures": {
    "format": true,
    "diagnostics": true,
    "documentLink": true
},
"go.languageServerFlags": ["-rpc.trace"],
"go.gotoSymbol.includeGoroot": true,
"go.gotoSymbol.includeImports": true,
"go.useCodeSnippetsOnFunctionSuggestWithoutType": true,
"go.useCodeSnippetsOnFunctionSuggest": true,
"go.autocompleteUnimportedPackages": true,
  1. 打斷點

本部分在備用電腦上面完成,go 版本為: go1.14.2

此次直接複用了前面文章go 中字串轉位元組切片的容量的 demo。三個斷點分別位於,main/test.go, runtime/proc.go 和 runtime/string.go.

  1. 執行

vscode 通過 F5 快捷鍵即可快速開始 debug

接下來, 你就可以開始快樂的 debug 之旅啦

debug 不出現在 call stack 的函式

細心的同學肯定已經發現了,在上面 vscode 圖形化 debug 的呼叫棧裡面並沒有 runtime/string.go 的影子。接下來, 我們結合本篇的主題繼續往下分析

相信看過我切片真的是引用嘛?這篇文章的同學,心裡已經基本有數了。對於這種即沒有呼叫棧也沒有明確呼叫者的函式,我們遵循以下兩點即可完成對它的 debug

  1. 首先檢視其彙編程式碼
# go程式碼轉匯編
go tool compile -N -l -S test.go

關鍵彙編程式碼如下:

如上圖所示,我們發現了stringtoslicebyte函式, 這樣我們就可以打斷點了, 只要打上了斷點就可以快樂的除錯了

  1. runtime 函式打斷點時機

部分 rumtime 函式打好斷點後, debug 程式會無法啟動, 這個時候就需要延遲打點 (“延遲打點” 為筆者自己總結的名字) 了。

首先,在 main 函式的入口處打一個斷點(呼叫 runtime 函式之前的斷點均可),刪除 runtime 函式的斷點。

最後, 等待 debug 程式啟動了,再給 runtime 函式打上斷點即可。

至此, 祝各位開啟快樂的 debug 之旅。

注: 寫本文時, 筆者所用 go 版本為: go1.13.4;

生命不息, 探索不止, 後續將持續更新有關於 go 的技術探索

原創不易, 卑微求關注收藏二連.

更多原創文章乾貨分享,請關注公眾號
  • go runtime debug 小技巧
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章