日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
一個Demo學會使用GoDelve調(diào)試

本文轉(zhuǎn)載自微信公眾號「腦子進煎魚了」,作者陳煎魚。轉(zhuǎn)載本文請聯(lián)系腦子進煎魚了公眾號。

創(chuàng)新互聯(lián)建站是一家專業(yè)從事成都網(wǎng)站設計、網(wǎng)站建設的網(wǎng)絡公司。作為專業(yè)網(wǎng)站設計公司,創(chuàng)新互聯(lián)建站依托的技術實力、以及多年的網(wǎng)站運營經(jīng)驗,為您提供專業(yè)的成都網(wǎng)站建設、成都全網(wǎng)營銷及網(wǎng)站設計開發(fā)服務!

大家好,我是煎魚。

在 Go 語言中,除了 go tool 工具鏈中的 pprof、trace 等剖析工具的大利器外。常常還會有小伙伴問,有沒有更好用,更精細的,

大家總嫌棄 pprof、trace 等工具,不夠細,沒法一口氣看到根因,或者具體變量...希望能夠最好能追到代碼級別調(diào)試的,看到具體變量的值是怎么樣的,隨意想怎么看怎么看的那種。

為此今天給大家介紹 Go 語言強大的 Delve (dlv)調(diào)試工具,來更深入問題剖析。

安裝

我們需要先安裝 Go delve,若是 Go1.16 及以后的版本,可以直接執(zhí)行下述命令安裝:

 
 
 
  1. $ go install github.com/go-delve/delve/cmd/dlv@latest

也可以通過 git clone 的方式安裝:

 
 
 
  1. $ git clone https://github.com/go-delve/delve
  2. $ cd delve
  3. $ go install github.com/go-delve/delve/cmd/dlv

在安裝完畢后,我們執(zhí)行 dlv version 命令,查看安裝情況:

 
 
 
  1. $ dlv version
  2. Delve Debugger
  3. Version: 1.7.0
  4. Build: $Id: e353a65161e6ed74952b96bbb62ebfc56090832b $

可以明確看到我們所安裝的版本是 v1.7.0。

演示程序

我們計劃用一個反轉(zhuǎn)字符串的演示程序來進行 Go 程序的調(diào)試。第一部分先是完成 stringer 包的 Reverse 方法。

代碼如下:

 
 
 
  1. package stringer
  2. func Reverse(s string) string {
  3.  r := []rune(s)
  4.  for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
  5.   r[i], r[j] = r[j], r[i]
  6.  }
  7.  return string(r)
  8. }

再在具體的 main 啟動函數(shù)中進行調(diào)用。代碼如下:

 
 
 
  1. import (
  2.  "fmt"
  3.  "github.com/eddycjy/awesome-project/stringer"
  4. )
  5. func main() {
  6.  fmt.Println(stringer.Reverse("腦子進煎魚了!"))
  7. }

輸出結(jié)果:

 
 
 
  1. !了魚煎進子腦

進行調(diào)試

Delve 是 Go 程序的源代碼級調(diào)試器。Delve 使您能夠通過控制流程的執(zhí)行與您的程序進行交互,查看變量,提供線程、goroutine、CPU 狀態(tài)等信息。

其一共支持如下 11 個子命令:

 
 
 
  1. Available Commands:
  2.   attach      Attach to running process and begin debugging.
  3.   connect     Connect to a headless debug server.
  4.   core        Examine a core dump.
  5.   dap         [EXPERIMENTAL] Starts a TCP server communicating via Debug Adaptor Protocol (DAP).
  6.   debug       Compile and begin debugging main package in current directory, or the package specified.
  7.   exec        Execute a precompiled binary, and begin a debug session.
  8.   help        Help about any command
  9.   run         Deprecated command. Use 'debug' instead.
  10.   test        Compile test binary and begin debugging program.
  11.   trace       Compile and begin tracing program.
  12.   version     Prints version.

我們今天主要用到的是 debug 命令,他能夠編譯并開始調(diào)試當前目錄下的主包,或指定的包,是最常用的功能之一。

接下來我們利用這個演示程序來進行 dlv 的深入調(diào)試和應用。

執(zhí)行如下命令:

 
 
 
  1.   awesomeProject dlv debug .
  2. Type 'help' for list of commands.
  3. (dlv) 

我們先在演示程序根目錄下執(zhí)行了 debug,進入了 dlv 的交互模式。

再使用關鍵字 b(break 的縮寫)對 main.main 方法設置斷點:

 
 
 
  1. (dlv) b main.main
  2. Breakpoint 1 (enabled) set at 0x10cbab3 for main.main() ./main.go:9
  3. (dlv) 

設置完畢后,我們可以看到方法對應的文件名、行數(shù)。接著我們可以執(zhí)行關鍵字 c(continue 的縮寫)跳轉(zhuǎn)到下一個斷點處:

 
 
 
  1. (dlv) c
  2. > main.main() ./main.go:9 (hits goroutine(1):1 total:1) (PC: 0x10cbab3)
  3.      4:  "fmt"
  4.      5: 
  5.      6:  "github.com/eddycjy/awesome-project/stringer"
  6.      7: )
  7.      8: 
  8. =>   9: func main() {
  9.     10:  fmt.Println(stringer.Reverse("腦子進煎魚了!"))
  10.     11: }
  11. (dlv) 

在斷點處,我看可以看到具體的代碼塊、goroutine、CPU 寄存器地址等運行時信息。

緊接著執(zhí)行關鍵字 n(next 的縮寫)單步執(zhí)行程序的下一步:

 
 
 
  1. (dlv) n
  2. > main.main() ./main.go:10 (PC: 0x10cbac1)
  3.      5: 
  4.      6:  "github.com/eddycjy/awesome-project/stringer"
  5.      7: )
  6.      8: 
  7.      9: func main() {
  8. =>  10:  fmt.Println(stringer.Reverse("腦子進煎魚了!"))
  9.     11: }

我們可以看到程序走到了 main.go 文件中的第 10 行中,并且調(diào)用了 stringer.Reverse 方法去處理。

此時我們可以執(zhí)行關鍵字 s(step 的關鍵字)進入到這個函數(shù)中去繼續(xù)調(diào)試:

 
 
 
  1. (dlv) s
  2. > github.com/eddycjy/awesome-project/stringer.Reverse() ./stringer/string.go:3 (PC: 0x10cb87b)
  3.      1: package stringer
  4.      2: 
  5. =>   3: func Reverse(s string) string {
  6.      4:  r := []rune(s)
  7.      5:  for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
  8.      6:   r[i], r[j] = r[j], r[i]
  9.      7:  }
  10.      8:  return string(r)

輸入后,調(diào)試的光標會到 Reverse 方法上,此時我們可以調(diào)用關鍵字 p(print 的縮寫)傳出所傳入的變量的值:

 
 
 
  1. (dlv) p s
  2. "腦子進煎魚了!"

此處函數(shù)的形參變量是 s,輸出了 “腦子進煎魚了!”,與我們所傳入的是一致的。

但故事一般沒有這么的簡單,會用到 Delve 來調(diào)試,說明是比較細致、隱患的 BUG。為此我們大多需要更進一步的深入。

我們繼續(xù)圍觀 Reverse 方法:

 
 
 
  1. 5:  for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
  2.  6:   r[i], r[j] = r[j], r[i]
  3.  7:  }

從表現(xiàn)來看,我們常常會懷疑是第 6 行可能是問題的所在。這時可以針對性的對第 6 行進行斷點查看:

 
 
 
  1. (dlv) b 6
  2. Breakpoint 2 (enabled) set at 0x10cb92c for github.com/eddycjy/awesome-project/stringer.Reverse() ./stringer/string.go:6

設置完斷點后,我們只需要執(zhí)行關鍵字 c,繼續(xù)下一步:

 
 
 
  1. (dlv) c
  2. > github.com/eddycjy/awesome-project/stringer.Reverse() ./stringer/string.go:6 (hits goroutine(1):1 total:1) (PC: 0x10cb92c)
  3.      1: package stringer
  4.      2: 
  5.      3: func Reverse(s string) string {
  6.      4:  r := []rune(s)
  7.      5:  for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
  8. =>   6:   r[i], r[j] = r[j], r[i]
  9.      7:  }
  10.      8:  return string(r)
  11.      9: }

走到對應的代碼片段后,執(zhí)行關鍵字 locals:

 
 
 
  1. (dlv) locals
  2. r = []int32 len: 7, cap: 32, [...]
  3. j = 6
  4. i = 0

我們就可以看到對應的變量 r, i, j 的值是多少,可以根據(jù)此來分析程序流轉(zhuǎn)是否與我們預想的一致。

另外也可以調(diào)用關鍵字 set 去針對特定變量設置期望的值:

 
 
 
  1. (dlv) set i = 1
  2. (dlv) locals
  3. r = []int32 len: 7, cap: 32, [...]
  4. j = 6
  5. i = 1

設置后,若還需要繼續(xù)排查,可以繼續(xù)調(diào)用關鍵字 c 去定位,這種常用于特定變量的特定值的異常,這樣一設置一調(diào)試基本就能排查出來了。

在排查完畢后,我們可以執(zhí)行關鍵字 r(reset 的縮寫):

 
 
 
  1. (dlv)  r
  2. Process restarted with PID 56614

執(zhí)行完畢后,整個調(diào)試就會重置,像是前面在打斷點時所設置的變量值就會恢復。

若要查看設置的斷點情況,也可以執(zhí)行關鍵字 bp 查看:

 
 
 
  1. (dlv) bp
  2. Breakpoint runtime-fatal-throw (enabled) at 0x1038fc0 for runtime.fatalthrow() /usr/local/Cellar/go/1.16.2/libexec/src/runtime/panic.go:1163 (0)
  3. Breakpoint unrecovered-panic (enabled) at 0x1039040 for runtime.fatalpanic() /usr/local/Cellar/go/1.16.2/libexec/src/runtime/panic.go:1190 (0)
  4.  print runtime.curg._panic.arg
  5. Breakpoint 1 (enabled) at 0x10cbab3 for main.main() ./main.go:9 (0)
  6. Breakpoint 2 (enabled) at 0x10cb92c for github.com/eddycjy/awesome-project/stringer.Reverse() ./stringer/string.go:6 (0)

查看斷點情況后,若有部分已經(jīng)排除了,可以調(diào)用關鍵字 clearall 對一些斷點清除:

 
 
 
  1. (dlv) clearall main.main
  2. Breakpoint 1 (enabled) cleared at 0x10cbab3 for main.main() ./main.go:9

若不指點斷點,則會默認清除全部斷點。

在日常的 Go 工程中,若都從 main 方法進入就太繁瑣了。我們可以直接借助函數(shù)名進行調(diào)式定位:

 
 
 
  1. (dlv) funcs Reverse
  2. github.com/eddycjy/awesome-project/stringer.Reverse
  3. (dlv) b stringer.Reverse
  4. Breakpoint 3 (enabled) set at 0x10cb87b for github.com/eddycjy/awesome-project/stringer.Reverse() ./stringer/string.go:3
  5. (dlv) c
  6. > github.com/eddycjy/awesome-project/stringer.Reverse() ./stringer/string.go:3 (hits goroutine(1):1 total:1) (PC: 0x10cb87b)
  7.      1: package stringer
  8.      2: 
  9. =>   3: func Reverse(s string) string {
  10.      4:  r := []rune(s)
  11.      5:  for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
  12.      6:   r[i], r[j] = r[j], r[i]
  13.      7:  }
  14.      8:  return string(r)

緊接著其他步驟都與先前的一樣,進行具體的調(diào)試就好了。我們也可以借助 Go 語言的公共函數(shù)進行計算:

 
 
 
  1. (dlv) p len(r)-1
  2. 6

也可以借助關鍵字 vars 查看某個包下的所有全局變量的值,例如:vars main。這種方式對于查看全局變量的情況非常有幫助。

排查完畢后,執(zhí)行關鍵字 exit 就可以愉快的退出了:

 
 
 
  1. (dlv) exit

解決完問題,可以下班了 :)

總結(jié)

在 Go 語言中,Delve 調(diào)試工具是與 Go 語言親和度最高的,因為 Delve 是 Go 語言實現(xiàn)的。其在我們?nèi)粘9ぷ髦?,非常常用?/p>

像是假設程序的 for 循環(huán)運行到第 N 次才出現(xiàn) BUG 時,我們就可以通過斷點對應的方法和代碼塊,再設置變量的值,進行具體的查看,就可以解決。


網(wǎng)頁標題:一個Demo學會使用GoDelve調(diào)試
瀏覽路徑:http://www.5511xx.com/article/dhdcscc.html