GO 学习笔记之四 工具(1)远程调试工具 dlv
一、背景
go 开发的程序需要编译成二进制放在环境上之后,通过 ./二进制文件名称 (linux服务器上的启动方式) 进行启动。 当程序允许过程中,如果发现有问题,此时希望能够 向Java 一样可以通过工具进行代码远程调试,这样可以更快发现问题。此时可以使用 dlv 工具。
二、安装
1、手动安装
当需要调试的服务器是离线的情况下,此时我们希望能够进行手动安装
1.1 下载源码 (Releases · go-delve/delve)

由于我的go版本使用的是 1.24.2, 所以这里也下载了 1.24.2 对应的源码
1.2 编译源码
- 将下载的 delve-1.24.2.tar.gz 上传到服务器上(本文章放在了 /opt/go/tool 下,go 安装在了 /opt/go/go 下)
 - tar -zxvf delve-1.24.2.tar.gz
 - cd delve-1.24.2
 
- go build github.com/go-delve/delve/cmd/dlv 在当前目录下生成了 dlv文件
 


1.3 安装
- 将 dlv 文件移动动 go path 目录下。 (\cp dlv /opt/go/go/bin)
 - dlv version 查看版本
 

2、利用 go 环境进行安装
环境中已经安装上了go,且该环境可以连网络 或者 go env 中的代理可以连接上,此时可以利用go 直接安装 dlv

2.1
三、配置远程调试环境
1、在开发工具 Visual Studio Code 中配置 dlv
- 在开发工具中打开你的 go 工程
 - 打开调试模式菜单下的配置 。。。 左侧点击“有爬虫的图标”,点击上侧的 的下拉图标,可以看到 一些菜单, 点击 “添加配置(xxxx)”,其中 xxxx 是你的go程序目录名称
 

- 右侧出现 launch.json文件
 
2、配置 launch.json
在文件中添加如下配置内容

- name:调试名称
 - type :默认 go
 - request:attach
 - mode:remote
 - remotePath:填写远程服务器上 go 二进制程序 源码所在路径
 - port:远程服务器上开启的 dlv 调试端口
 - host:远程服务器的IP
 - trace:verbose
 - showLog:true 是否打开日志
 
3、将go 二进制程序的源码放到 远程服务器上

四、启动远程调试
1、远程服务器 开启 dlv 调试进程
- 远程到服务器 go 二进制源码所在目录下
 - dlv debug --headless --listen=:2366 --api-version=2 --log
 

可以看到 启动在 2366端口上,且go二进制程序已经运行
2、启动 Visual Studio 上的 远程调试
 
3、在 Visual Studio 上的 dlv调试时开启dlv日志(待确认)
3.1 Visual Studio 上 开启日志
1) 选择设置图标,打开设置菜单

2)出现 设置页面,输入 log level , 将 remote.ssh 更改成 trace 级别
3)Ctrl+ Shift + U 打开输出面板,选择 Go Debug 模式

3.2 launch.json 上配置日志相关配置项
需要加上两个配置项:
"trace": "verbose", "showLog": true,
 
五、用法深入研究
六、常见问题
1、启动go文件不存在于程序源码根路径下且程序依赖C++库。
1.1 具体场景描述
main.go文件不存在,程序入口go文件不在源代码根目录下,而是在其它子目录下;代码中存在加载C++库文件的逻辑。目录结构如下:

1.2 问题
1.2.1 远程服务器执行 dlv debug 命令系列问题
此情况下,通过dlv调式(在源码根路径下 -- go.mod 所在目录, 执行dlv 命令: dlv debug --listen=:2366 --headless=true --api-version=2 --log ./core/start/start.go),遇到如下问题:
1.2.1.1 直接执行 dlv debug --listen=:2366 --headless=true --api-version=2 --log ./core/start/start.go 提示 找不到C++库提供的方法

这个表示在 dlv debug 的时候去生成对应的 可执行文件时找不到需要链接的 C++库文件。
因此通过资料查找,可使用 --build-flags 指定 需要链接库的绝对路径,但仍出现 1.2.1.2 的问题。
1.2.1.2 直接执行 dlv debug --build-flags="-ldflags='-L/opt/xxx/x86/base/identify/lib/linux/x86_64 -llibIdentify'" --listen=:2345 --headless ./core/start/start.go,提示 命令存在问题
 
这个错误是因为 -L 和 -l 是 链接器标志(linker flags),但您将它们放在了 --build-flags 的 -ldflags 参数中,而 -ldflags 是传递给 Go 链接器的,格式有特定要求。直接使用 -L 和 -l 在 -ldflags 中会导致解析错误。
1.2.1.3 解决方案
a)  使用 #cgo 指令(推荐)
在您的 Go 代码(如 center.go 或相关文件)中,通过 // #cgo 指令指定链接参数:
// #cgo LDFLAGS: -L/opt/xxx/x86/base/identify/lib/linux/x86_64 -lIdentify // #include "identify.h" // 确保头文件路径正确 import "C"
然后直接使用 dlv debug(无需 --build-flags):
dlv debug --listen=:2345 --headless ./core/start/start.go
PS:调试的时候可以 通过 #cgo命令写入库的绝对路径,但是实际代码不能写成绝对路径,主要是因为实际安装路径不会是这个绝对路径对应的安装目录
b) 通过环境变量传递链接参数
设置 CGO_LDFLAGS 环境变量(适用于临时调试):
export CGO_LDFLAGS="-L/optxxx/x86/base/identify/lib/linux/x86_64 -lIdentify" dlv debug --listen=:2345 --headless ./core/start/start.go
c)  使用 --build-flags 的正确格式
如果必须使用 --build-flags,需将链接器参数作为字符串传递给 -ldflags:
dlv debug --build-flags="-ldflags='-extldflags \"-L/opt/xxx/x86/base/identify/lib/linux/x86_64 -lIdentify\"'" --listen=:2345 --headless ./core/start/start.go
PS:经过考虑以及使用的方便性,使用了最后一种方案
1.2.2 通过 dlv debug --build-flags 方式指定了编译时C++库路径,此时dlv成功启动,但是在VSCODE工具上配置好 launch.json远程调试之后,点击启动,dlv debug端直接报错 “/opt/xxx/x86/__debug_bin2434698469: error while loading shared libraries: libIdentify.so: cannot open shared object file: No such file or directory”

1.2.2.1 分析
根据错误提示是 _debug_binxxxx 这个程序运行时找不到 要用的C++库 libIdentify.so (PS:将这个so库直接放在 _debug_binxxx 所在目录 或 入口start.go 文件所在目录都不生效,不知道为啥)
1.2.2.2 解决方案
dlv debug 在远程服务器执行之前,先 通过export 方式设置C++库路径 。命令为:
export LD_LIBRARY_PATH=/opt/xxxx/x86/:$LD_LIBRARY_PATH

从上图可以看到 远程联调成功开启。
1.2.3 远程服务器上放置的源码结构与本地的一致,但是VSCODE打上断点不生效
{ // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "Connect to server", "type": "go", "request": "attach", "mode": "remote", "remotePath": "/opt/xxx/x86", "port": 2366, "host": "10.19.219.79", "trace": "verbose", "showLog": true, "cwd": "${workspaceFolder}" }, ] }
这里给 入口.go 文件上打上了断点,dlv 远程调试开启之后,有如下提示:

 
1.2.3.1 分析
根据网上的资料给出的结论均是由于本地代码路径和远程服务器上的不一致导致的,但是思考下来感觉大概率是本地没有找到正确的映射目录所致,因此查询可以设置本地和远程路径的各种配置。
1.2.3.2 解决办法
{ // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "Connect to server", "type": "go", "request": "attach", "mode": "remote", "port": 2366, "host": "10.19.219.79", "trace": "verbose", "showLog": true, "logOutput": "debugger", "debugAdapter": "dlv-dap", "dlvFlags": [ "--check-go-version=false" ], "substitutePath": [ { "from": "${workspaceFolder}", "to": "/opt/xxx/x86" } ] }, ] }
                    
                
                
            
        
浙公网安备 33010602011771号