用VSCode Debug GO程式吧

Posted by Elizabeth Huang on Mon, Mar 25, 2024

這篇分為兩個部分,需要的人可以跳著看

  1. 本地開發
  2. Docker開發

Debug GO

官方文件推薦使用Delve,而不是GDB 雖然Delve可以用command來debug,但我已經很習慣用VSCode邊寫邊debug了,所以接下來來設定環境吧~

本地開發

側邊欄選擇Run and Debug,點擊create a launch.json file,然後選擇Go: Launch Package,VSCode會自動建立一個.vscode/launch.json檔,長得像這樣:

 1{
 2    // Use IntelliSense to learn about possible attributes.
 3    // Hover to view descriptions of existing attributes.
 4    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
 5    "version": "0.2.0",
 6    "configurations": [
 7        {
 8            "name": "Launch Package",
 9            "type": "go",
10            "request": "launch",
11            "mode": "auto",
12            "program": "${fileDirname}"
13        }
14    ]
15}

然後就可以下斷點,F5開始debug,很簡單吧!

但我用的是Docker

現在很多人用Docker作為開發環境,尤其是Docker Compose能一次開很多服務真的很方便

這種情況可以用Remote Debug

一樣在側邊欄選擇Run and Debug,點擊create a launch.json file,然後選擇Connect to a server

VSCode也會建立一個.vscode/launch.json檔,但還沒完,需要修改兩個參數:

  • port:這個隨便取,不要跟其他服務撞到就好
  • substitutePath:怎麼把code volume 到conatiner裡面,這裡就怎麼設 最後我的launch.json長這樣:
 1{
 2    // Use IntelliSense to learn about possible attributes.
 3    // Hover to view descriptions of existing attributes.
 4    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
 5    "version": "0.2.0",
 6    "configurations": [
 7        {
 8            "name": "Connect to server",
 9            "type": "go",
10            "request": "attach",
11            "mode": "remote",
12            "substitutePath": [
13                {
14                    "from": "${workspaceFolder}",
15                    "to": "/app"
16                },
17            ],
18            "port": 4040,
19            "host": "127.0.0.1"
20        }
21    ]
22}

現在來給net/http的範例code寫一個Dockerfile

1FROM golang:1.21.4-alpine
2
3RUN mkdir /app
4COPY .. /app
5WORKDIR /app
6
7RUN go install github.com/go-delve/delve/cmd/dlv@master
8ENTRYPOINT dlv debug --headless --continue --listen :4040 --accept-multiclient .

--continue可以在delve 伺服器一啟動後立刻開始debug,而用了--continue以後就要一並使用--accept-multiclient

注意compose.yaml也要設定port mapping和volume!

 1version: "3"
 2services:
 3  app:
 4    build:
 5      dockerfile: Dockerfile
 6      context: .
 7    volumes:
 8      - ./:/app
 9    ports:
10      - 8080:8080
11      - 4040:4040
12    networks:
13      - go-docker-net
14
15networks:
16  go-docker-net:

跟CompileDaemon一起

開發的時候,每次變更都要手動build非常不方便,所以我都會用CompileDaemon,它可以偵測*.go檔案變更,自動build專案

每次編譯之後,可以用CompileDaemon的command option,寫一個script 發送SIGINT終止Delve的headless server

kill_and_debug.sh

1#! /bin/bash
2kill -SIGINT $(ps aux | grep '[d]lv exec' | awk '{print $1}')
3dlv exec --headless --continue --listen :4040 --accept-multiclient ./app

修改一下Dockerfile

 1FROM golang:1.21.4-alpine
 2
 3# Environment variables which CompileDaemon requires to run
 4ENV PROJECT_DIR=/app \
 5    GO111MODULE=on \
 6    CGO_ENABLED=0
 7
 8RUN mkdir /app
 9COPY .. /app
10WORKDIR /app
11
12RUN go get github.com/githubnemo/CompileDaemon
13RUN go install github.com/githubnemo/CompileDaemon
14RUN go install github.com/go-delve/delve/cmd/dlv@master
15
16ENTRYPOINT CompileDaemon -build="go build -o app" -command="sh kill_and_debug.sh"

每次在儲存新修改之前,先斷開remote debug的連接,儲存後等待build,之後就可以跟平常一樣debug了~

參考