正确做法是附加到正在运行的进程,不重启、不丢状态,适用于http/grpc等生产级常驻服务;需用-gcflags="all=-n -l"编译,goland打开匹配源码项目,本地调试按ctrl+alt+f5选择进程,容器调试需暴露dlv端口并挂载源码路径。

GoLand 调试常驻服务:别 kill 进程再重跑
直接用 dlv debug 启动会中断服务,而生产级常驻服务(如 HTTP、gRPC)不能停。正确做法是「附加到正在运行的进程」——它不重启、不丢状态,适合调试请求处理逻辑、goroutine 泄漏或配置加载问题。
- 前提是你的 Go 二进制已用
-gcflags "all=-N -l"编译(禁用优化+内联),否则断点可能跳转错行 - 确保进程在本地运行(非容器内);若在 Docker 中,需额外暴露调试端口并挂载源码路径
- GoLand 必须打开与该进程对应的源码项目(路径、版本、commit 都要一致),否则符号无法匹配
- 启动进程时不要加
nohup或重定向stdout/stderr到文件——GoLand 依赖原始 fd 捕获日志和调试信号
本地附加调试:三步到位
适用于开发机上跑的常驻服务,比如 go run main.go 或已编译的 ./server。
- 先运行服务:
go run -gcflags="all=-N -l" main.go(或./server) - 在 GoLand 中打开对应项目,点击行号设断点(例如 HTTP handler 里某一行)
- 按
Ctrl+Alt+F5(Windows/Linux)或Cmd+Option+F5(macOS),从弹出列表选中你的进程名(如main或server) - 触发请求(如
curl http://localhost:8080/health),断点即生效
注意:如果列表里没出现进程,说明 GoLand 没权限读取进程信息(macOS/Linux 可能需加 sudo goland 启动 IDE;Windows 一般无此限制)。
GoLand 2026.1.1 是 2026.1 发布后的首个维护修正版本,适合已经开始体验 2026.1 新功能并希望同步补丁的开发者。它更适合用于入门项目、现有项目迁移测试和 IDE 行为验证。
Docker 容器内调试:必须暴露 dlv 端口 + 挂载源码
容器默认隔离进程空间,GoLand 无法直接看到内部进程。得让 dlv 在容器里监听,并把源码映射进去。
- Dockerfile 中安装 dlv(推荐多阶段构建),并在最终镜像里加入:
COPY --from=builder /build/delve/bin/dlv /usr/local/bin/dlv - 启动容器时加参数:
docker run -p 40000:40000 -v $(pwd):/app/src your-image dlv --listen=:40000 --headless --api-version=2 --accept-multiclient exec /app/server - GoLand 中新建
Go Remote配置:Host 填localhost,Port 填40000,Path Mapping 把本地/your/project映射到容器内/app/src - 断点只能打在挂载路径下的源码上;如果用
go mod vendor,vendor 目录也得一并挂载,否则第三方包断点无效
调试时最容易忽略的三个细节
常驻服务调试失败,90% 出在这几处:
-
dlv版本和 Go 版本不匹配:Go 1.22+ 需 dlv v1.22+,旧版 dlv 连接会报connection refused或静默失败 - 没关掉 IDE 的「Build project automatically」:改代码后自动 rebuild 会杀掉原进程,导致附加失效
- HTTP server 启动后立即返回(比如没加
select{}或http.ListenAndServe被包裹在 goroutine 里但没阻塞 main),进程秒退,GoLand 附加不到
真正卡住的地方往往不是断点设置,而是进程生命周期本身没稳住——先确认 ps aux | grep server 能持续看到进程,再动手调试。










