国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

一個 Demo 學會使用 Go Delve 調試

開發 后端
在 Go 語言中,Delve 調試工具是與 Go 語言親和度最高的,因為 Delve 是 Go 語言實現的。其在我們日常工作中,非常常用。

[[412997]]

本文轉載自微信公眾號「腦子進煎魚了」,作者陳煎魚。轉載本文請聯系腦子進煎魚了公眾號。

大家好,我是煎魚。

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

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

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

安裝

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

  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 

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

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

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

演示程序

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

代碼如下:

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

再在具體的 main 啟動函數中進行調用。代碼如下:

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

輸出結果:

  1. !了魚煎進子腦 

進行調試

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

其一共支持如下 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 binaryand 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 命令,他能夠編譯并開始調試當前目錄下的主包,或指定的包,是最常用的功能之一。

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

執行如下命令:

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

我們先在演示程序根目錄下執行了 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)  

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

  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 寄存器地址等運行時信息。

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

  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 行中,并且調用了 stringer.Reverse 方法去處理。

此時我們可以執行關鍵字 s(step 的關鍵字)進入到這個函數中去繼續調試:

  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) 

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

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

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

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

我們繼續圍觀 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:  } 

從表現來看,我們常常會懷疑是第 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 

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

  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: } 

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

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

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

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

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

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

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

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

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

若要查看設置的斷點情況,也可以執行關鍵字 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) 

查看斷點情況后,若有部分已經排除了,可以調用關鍵字 clearall 對一些斷點清除:

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

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

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

  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) 

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

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

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

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

  1. (dlv) exit 

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

總結

在 Go 語言中,Delve 調試工具是與 Go 語言親和度最高的,因為 Delve 是 Go 語言實現的。其在我們日常工作中,非常常用。

 

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

 

責任編輯:武曉燕 來源: 腦子進煎魚了
相關推薦

2021-07-28 08:53:53

GoGDB調試

2020-07-10 16:52:43

DelveGo程序開源

2021-07-29 07:55:19

Demo 工作池

2023-03-29 08:18:16

Go調試工具

2022-05-23 09:22:20

Go語言調試器Delve

2023-11-10 09:20:28

Java工具

2021-12-28 07:20:43

Hippo WebAssembly云原生

2023-12-27 07:40:43

HTTP服務器負載均衡

2021-07-26 05:07:23

Swift萬花尺代碼

2021-10-09 10:50:30

JavaScript編程開發

2020-12-08 08:46:07

GoJava工具

2025-05-20 09:39:57

GogRPC微服務

2021-05-30 07:56:51

QSettingsLog4Qt變量

2024-08-21 08:21:45

CNN算法神經網絡

2024-08-02 10:28:13

算法NLP模型

2024-06-03 08:09:39

2024-07-19 08:21:24

2024-06-06 09:44:33

2024-12-19 00:16:43

2009-11-05 15:25:36

WCF服務端配置
點贊
收藏

51CTO技術棧公眾號

春暖花开成人亚洲区| 欧美专区福利在线| 国产精品777| 成人18免费| 波多野结衣一区二区三区免费视频| 国产精品一区二区三区四区 | 亚洲女人av| 欧美一区二区视频97| 亚洲精品一区二区在线播放∴| 午夜精品久久久久久久99热浪潮| 国产一级不卡视频| 蜜桃传媒在线| 国产精品久久久久一区| 五十路熟女丰满大屁股| 丁香婷婷综合色啪| 国产资源第一页| 国产一区二区调教| 九九久久九九久久| 国产精品1区二区.| 国产精品成人久久电影| 国产盗摄精品一区二区三区在线| av电影一区二区三区| 寂寞少妇一区二区三区| 国产盗摄视频在线观看| 国产成人在线视频免费播放| 手机看片日韩国产| 国产高清亚洲一区| 日韩一级片免费视频| 99在线精品观看| 欧美日韩大尺度| 99视频精品在线| 国产淫片av片久久久久久| 国产精品色哟哟网站| 意大利激情丛林无删减版dvd| 亚洲成av人**亚洲成av**| 神马久久精品| 日韩精品一区国产麻豆| 午夜影视一区二区三区| 色噜噜久久综合伊人一本| 亚洲1区在线| 国产精品美女999| 不卡视频观看| 欧美高清一区二区| 日韩欧美午夜| 国产精品一国产精品| 国产日韩欧美夫妻视频在线观看| 97视频免费在线看| 亚洲综合最新在线| 日韩黄色免费电影| 国产无限制自拍| 亚洲欧美国产77777| 国产人成在线观看| 亚洲精品久久7777777| 亚洲小说春色综合另类电影| 97国产精品免费视频| 欧美网站在线| 国产成人免费高清视频| 成人免费一区二区三区在线观看| 国产中文在线观看| 亚洲欧美一区二区激情| 岳的好大精品一区二区三区| 国产高清精品一区二区三区| 国产一区二区精品久久| 明星乱亚洲合成图.com| 91精品黄色片免费大全| 精品午夜视频| 女女同性女同一区二区三区91| 99麻豆久久久国产精品免费优播| 久草电影在线| 亚洲色图美腿丝袜| 我不卡影院28| 日韩欧美一区二| 欧美性猛片aaaaaaa做受| 日韩福利影视| 蜜桃999成人看片在线观看| 国产精品麻豆一区二区| 国产后进白嫩翘臀在线观看视频| 欧美亚洲视频在线看网址| 蜜臀va亚洲va欧美va天堂| 91佛爷在线| 一区二区三区动漫| 国产一区二区三区四区三区四| 水蜜桃色314在线观看| 欧美在线免费视屏| 国产一区二区三区亚洲综合| 色影视在线视频资源站| 亚洲三级av在线| 国产精品igao视频网网址不卡日韩| 国产精品乱看| 亚洲最大综合网| 日韩精品一区二区三区视频 | 高清一区二区中文字幕| 国产精品视频入口| 国产精品水嫩水嫩| 亚洲性受xxx喷奶水| 99精品国产高清在线观看| 久久精品亚洲国产奇米99| 在线免费观看污| 91九色蝌蚪国产| 成人免费一区二区三区视频| 日韩另类视频| 亚洲国产欧洲综合997久久| 日韩欧美一区二区三区久久| 国产精品网站在线看| 牛牛影视久久网| 69堂免费视频| 涩涩视频在线| 国产伦精品一区二区三区照片91| 一区二区中文字幕在线| 久久天堂影院| av 日韩 人妻 黑人 综合 无码| 欧美唯美清纯偷拍| 伊人青青综合网| 亚洲一本大道| 日韩免费观看视频| 国产精品久久99| 懂色av一区二区| 粉嫩虎白女毛片人体| 亚洲先锋影音| 成人在线爆射| 男女爱爱免费网站| 亚洲日韩欧美视频一区| 亚洲欧美日韩视频二区| 亚洲va男人天堂| 国产精品久久久久久av福利软件 | 热久久精品免费视频| 亚洲国产精品免费| 肉色丝袜一区二区| 尤物yw193can在线观看| 99久久99久久免费精品蜜臀| 在线免费黄色| 久久国产日韩欧美| 欧美一区国产二区| 日本亚洲一区二区| 91禁在线看| 欧美一级免费在线观看| 亚洲欧美一区二区精品久久久| 国产久卡久卡久卡久卡视频精品| а√天堂8资源在线| 久久香蕉视频网站| 正在播放一区二区| 亚洲成人激情在线| 精品精品欲导航| 久久美女性网| 国产视频网站在线| 国产精品美女诱惑| 日韩午夜在线观看| 激情综合一区二区三区| 姬川优奈av一区二区在线电影| www在线观看免费| 午夜精品美女自拍福到在线| 亚洲欧美国产三级| 欧美在线播放| 黄色精品免费看| 亚洲一区二区三区午夜| 中文字幕精品久久久久| 中文字幕成人网| 在线观看日韩| 欧美videos另类精品| 美脚丝袜脚交一区二区| 97在线免费视频| 欧美午夜精品久久久久久人妖| 亚洲乱码久久| 欧美日韩尤物久久| 黄色成人av| 欧美精品v日韩精品v国产精品| 亚洲精品国产精品国自产在线| 久久亚洲精品国产精品紫薇| 经典一区二区| 97超碰在线公开在线看免费| 亚洲熟妇无码一区二区三区导航| 琪琪第一精品导航| 欧美日韩在线播放三区| 成人精品视频一区二区三区尤物| 久久精品66| av大片在线看| 麻豆tv在线播放| 国产精品中文在线| 日韩免费成人网| 欧美国产日韩亚洲一区| 亚洲巨乳在线| 国模大尺度视频一区二区| 久久天天躁狠狠躁夜夜躁2014| 欧洲精品久久久| 亚洲综合社区网| 女同一区二区| 国产成人精品一区二区三区福利| 亚洲精品久久久久久一区二区| 国产精品久久久亚洲| 99热国产免费| 国产欧美韩日| 26uuu亚洲| 久久精品国产**网站演员| 狠狠色综合日日| 国产在线麻豆精品观看| 国产精品白丝在线| 欧美日韩国产区一| 亚洲欧洲国产精品| 66久久国产| 久久天天久久|