首頁 後端開發 Golang 掌握 Emacs 中的 Golang 調試

掌握 Emacs 中的 Golang 調試

Dec 02, 2024 am 11:56 AM

介紹

自從我開始使用 Golang 開發以來,我並沒有真正使用過調試器。相反,我天真地在各處添加 fmt.Print 語句來驗證我的程式碼?雖然列印語句和日誌可能也是您的第一個調試本能,但在處理大型且複雜的程式碼庫、複雜的運行時行為以及(當然!)似乎無法重現的複雜並發問題時,它們通常會出現不足。

開始處理更複雜的專案(例如這個:https://github.com/cloudoperators/heureka)後,我必須強迫自己更深入地了解delve(Golang 偵錯器)並了解Emacs 提供的功能與它互動。雖然 Go 生態系統提供了出色的調試工具,但將它們整合到舒適的開發工作流程中可能具有挑戰性。

在這篇文章中,我將詳細闡述 Emacs、Delve 和 dape 的強大組合。這些工具共同創造了模仿(並且常常超越)傳統 IDE 的調試體驗,同時保留了 Emacs 聞名的靈活性和可擴展性。

這是你所期望的:

  • 使用 dape 設定和設定 Delve
  • 調試標準應用程式和 Ginkgo 測試(這就是我目前正在使用的?)
  • 使用 Emacs 特定的自訂功能來最佳化您的偵錯工作流程

設定開發環境

在這篇文章中,我假設您已經有一些 Emacs 經驗,現在了解如何配置套件和編寫小的 Elisp 片段。我個人使用Straight.el 作為套件管理器,minimal-emacs.d 作為最小的普通Emacs 配置(以及我自己的自訂),dape 作為調試適配器客戶端,eglot 作為我的LSP 客戶端

所需的 Emacs 軟體包

對於 Emacs 29 用戶,eglot 是內建的。看看為 gopls 設定 eglot 和一些更進階的 gopls 設定。我們先加入 dape:

(use-package dape
  :straight t
  :config
  ;; Pulse source line (performance hit)
  (add-hook 'dape-display-source-hook 'pulse-momentary-highlight-one-line)

  ;; To not display info and/or buffers on startup
  ;; (remove-hook 'dape-start-hook 'dape-info)
  (remove-hook 'dape-start-hook 'dape-repl))
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

和運行模式:

(use-package go-mode
  :straight t
  :mode "\.go\'"
  :hook ((before-save . gofmt-before-save))
  :bind (:map go-mode-map
              ("M-?" . godoc-at-point)
              ("M-." . xref-find-definitions)
              ("M-_" . xref-find-references)
              ;; ("M-*" . pop-tag-mark) ;; Jump back after godef-jump
              ("C-c m r" . go-run))
  :custom
  (gofmt-command "goimports"))
登入後複製
登入後複製
登入後複製
登入後複製

安裝所需的 Go 工具

安裝 Delve 和 gopls(LSP 伺服器):

# Install Delve
go install github.com/go-delve/delve/cmd/dlv@latest

# Install gopls
go install golang.org/x/tools/gopls@latest
登入後複製
登入後複製
登入後複製
登入後複製

此外,我還有一些我不時使用的其他工具:

go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
go install github.com/onsi/ginkgo/v2/ginkgo@latest

go install -v golang.org/x/tools/cmd/godoc@latest
go install -v golang.org/x/tools/cmd/goimports@latest
go install -v github.com/stamblerre/gocode@latest
go install -v golang.org/x/tools/cmd/gorename@latest
go install -v golang.org/x/tools/cmd/guru@latest
go install -v github.com/cweill/gotests/...@latest

go install -v github.com/davidrjenni/reftools/cmd/fillstruct@latest
go install -v github.com/fatih/gomodifytags@latest
go install -v github.com/godoctor/godoctor@latest
go install -v github.com/haya14busa/gopkgs/cmd/gopkgs@latest
go install -v github.com/josharian/impl@latest
go install -v github.com/rogpeppe/godef@latest
登入後複製
登入後複製
登入後複製
登入後複製

然後需要配置對應的Emacs套件:

(use-package ginkgo
  :straight (:type git :host github :repo "garslo/ginkgo-mode")
  :init
  (setq ginkgo-use-pwd-as-test-dir t
        ginkgo-use-default-keys t))

(use-package gotest
  :straight t
  :after go-mode
  :bind (:map go-mode-map
              ("C-c t f" . go-test-current-file)
              ("C-c t t" . go-test-current-test)
              ("C-c t j" . go-test-current-project)
              ("C-c t b" . go-test-current-benchmark)
              ("C-c t c" . go-test-current-coverage)
              ("C-c t x" . go-run)))

(use-package go-guru
  :straight t
  :hook
  (go-mode . go-guru-hl-identifier-mode))

(use-package go-projectile
  :straight t
  :after (projectile go-mode))

(use-package flycheck-golangci-lint
  :straight t
  :hook
  (go-mode . flycheck-golangci-lint-setup))

(use-package go-eldoc
  :straight t
  :hook
  (go-mode . go-eldoc-setup))

(use-package go-tag
  :straight t
  :bind (:map go-mode-map
              ("C-c t a" . go-tag-add)
              ("C-c t r" . go-tag-remove))
  :init (setq go-tag-args (list "-transform" "camelcase")))

(use-package go-fill-struct
  :straight t)

(use-package go-impl
  :straight t)

(use-package go-playground
  :straight t)
登入後複製
登入後複製
登入後複製
登入後複製

戴普配置

我使用 dape 而不是 dap 沒有什麼特別的原因。當我還在使用 MinEmacs 時,它就是其中的一部分,我只是習慣了它。如文件所述:

  • Dape 不支援 launch.json 文件,如果需要每個項目配置,請使用 dir-locals 和 dape-command。
  • Dape 允許使用者使用選項修改或新增 PLIST 條目到現有配置,從而增強了迷你緩衝區內的人體工學。
  • 沒有魔法,沒有像 ${workspaceFolder} 這樣的特殊變數。相反,函數和變數會在開始新會話之前解析。
  • 試著設想如果 vscode 不存在,如何在 Emacs 中實現偵錯適配器配置。

如果您曾經使用過 VSCode,您已經知道它使用 launch.json 來儲存不同的偵錯設定檔:

(use-package dape
  :straight t
  :config
  ;; Pulse source line (performance hit)
  (add-hook 'dape-display-source-hook 'pulse-momentary-highlight-one-line)

  ;; To not display info and/or buffers on startup
  ;; (remove-hook 'dape-start-hook 'dape-info)
  (remove-hook 'dape-start-hook 'dape-repl))
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

您有不同的欄位/屬性,根據此頁面,您可以在偵錯配置中進行調整:

Property Description
name Name for your configuration that appears in the drop down in the Debug viewlet
type Always set to "go". This is used by VS Code to figure out which extension should be used for debugging your code
request Either of launch or attach. Use attach when you want to attach to an already running process
mode For launch requests, either of auto, debug, remote, test, exec. For attach requests, use either local or remote
program Absolute path to the package or file to debug when in debug & test mode, or to the pre-built binary file to debug in exec mode
env Environment variables to use when debugging. Example: { "ENVNAME": "ENVVALUE" }
envFile Absolute path to a file containing environment variable definitions
args Array of command line arguments that will be passed to the program being debugged
showLog Boolean indicating if logs from delve should be printed in the debug console
logOutput Comma separated list of delve components for debug output
buildFlags Build flags to be passed to the Go compiler
remotePath Absolute path to the file being debugged on the remote machine
processId ID of the process that needs debugging (for attach request with local mode)

申請樣本

現在讓我們透過調試實作 REST API 的真實應用程式來將我們的知識付諸實踐。

專案結構

我們的範例是用於任務管理的 REST API,其架構如下:

(use-package dape
  :straight t
  :config
  ;; Pulse source line (performance hit)
  (add-hook 'dape-display-source-hook 'pulse-momentary-highlight-one-line)

  ;; To not display info and/or buffers on startup
  ;; (remove-hook 'dape-start-hook 'dape-info)
  (remove-hook 'dape-start-hook 'dape-repl))
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

核心組件

讓我們來看看核心元件

任務代表我們的核心領域模型:

(use-package go-mode
  :straight t
  :mode "\.go\'"
  :hook ((before-save . gofmt-before-save))
  :bind (:map go-mode-map
              ("M-?" . godoc-at-point)
              ("M-." . xref-find-definitions)
              ("M-_" . xref-find-references)
              ;; ("M-*" . pop-tag-mark) ;; Jump back after godef-jump
              ("C-c m r" . go-run))
  :custom
  (gofmt-command "goimports"))
登入後複製
登入後複製
登入後複製
登入後複製

TaskStore 處理我們的記憶體資料操作:

# Install Delve
go install github.com/go-delve/delve/cmd/dlv@latest

# Install gopls
go install golang.org/x/tools/gopls@latest
登入後複製
登入後複製
登入後複製
登入後複製

休息API

API 公開以下端點:

  • POST /task/create - 建立一個新任務
  • GET /task/get?id=; - 透過ID擷取任務
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
go install github.com/onsi/ginkgo/v2/ginkgo@latest

go install -v golang.org/x/tools/cmd/godoc@latest
go install -v golang.org/x/tools/cmd/goimports@latest
go install -v github.com/stamblerre/gocode@latest
go install -v golang.org/x/tools/cmd/gorename@latest
go install -v golang.org/x/tools/cmd/guru@latest
go install -v github.com/cweill/gotests/...@latest

go install -v github.com/davidrjenni/reftools/cmd/fillstruct@latest
go install -v github.com/fatih/gomodifytags@latest
go install -v github.com/godoctor/godoctor@latest
go install -v github.com/haya14busa/gopkgs/cmd/gopkgs@latest
go install -v github.com/josharian/impl@latest
go install -v github.com/rogpeppe/godef@latest
登入後複製
登入後複製
登入後複製
登入後複製

伺服器

這是伺服器實作:

(use-package ginkgo
  :straight (:type git :host github :repo "garslo/ginkgo-mode")
  :init
  (setq ginkgo-use-pwd-as-test-dir t
        ginkgo-use-default-keys t))

(use-package gotest
  :straight t
  :after go-mode
  :bind (:map go-mode-map
              ("C-c t f" . go-test-current-file)
              ("C-c t t" . go-test-current-test)
              ("C-c t j" . go-test-current-project)
              ("C-c t b" . go-test-current-benchmark)
              ("C-c t c" . go-test-current-coverage)
              ("C-c t x" . go-run)))

(use-package go-guru
  :straight t
  :hook
  (go-mode . go-guru-hl-identifier-mode))

(use-package go-projectile
  :straight t
  :after (projectile go-mode))

(use-package flycheck-golangci-lint
  :straight t
  :hook
  (go-mode . flycheck-golangci-lint-setup))

(use-package go-eldoc
  :straight t
  :hook
  (go-mode . go-eldoc-setup))

(use-package go-tag
  :straight t
  :bind (:map go-mode-map
              ("C-c t a" . go-tag-add)
              ("C-c t r" . go-tag-remove))
  :init (setq go-tag-args (list "-transform" "camelcase")))

(use-package go-fill-struct
  :straight t)

(use-package go-impl
  :straight t)

(use-package go-playground
  :straight t)
登入後複製
登入後複製
登入後複製
登入後複製

讓我們來看看我們的主要功能:

{
    "name": "Launch file",
    "type": "go",
    "request": "launch",
    "mode": "auto",
    "program": "${file}"
}
登入後複製
登入後複製

建立應用程式

讓我們啟動伺服器:

taskapi/
├── go.mod
├── go.sum
├── main.go
├── task_store.go
└── task_test.go
登入後複製
登入後複製

現在從不同的終端建立一個新任務:

import (
    "fmt"
)

type Task struct {
    ID          int    `json:"id"`
    Title       string `json:"title"`
    Description string `json:"description"`
    Done        bool   `json:"done"`
}
登入後複製
登入後複製

回應:

type TaskStore struct {
    tasks  map[int]Task
    nextID int
}

func NewTaskStore() *TaskStore {
    return &TaskStore{
        tasks:  make(map[int]Task),
        nextID: 1,
    }
}
登入後複製
登入後複製

讓我們看看是否可以取得它:

// CreateTask stores a given Task internally
func (ts *TaskStore) CreateTask(task Task) Task {
    task.ID = ts.nextID
    ts.tasks[task.ID] = task
    ts.nextID++
    return task
}

// GetTask retrieves a Task by ID
func (ts *TaskStore) GetTask(id int) (Task, error) {
    task, exists := ts.tasks[id]
    if !exists {
        return Task{}, fmt.Errorf("task with id %d not found", id)
    }
    return task, nil
}

// UpdateTask updates task ID with a new Task object
func (ts *TaskStore) UpdateTask(id int, task Task) error {
    if _, exists := ts.tasks[id]; !exists {
        return fmt.Errorf("task with id %d not found", id)
    }
    task.ID = id
    ts.tasks[id] = task
    return nil
}
登入後複製
登入後複製

回應:

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

// Server implements a web application for managing tasks
type Server struct {
    store *TaskStore
}

func (s *Server) handleCreateTask(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    var task Task
    if err := json.NewDecoder(r.Body).Decode(&task); err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    createdTask := s.store.CreateTask(task)
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(createdTask)
}

func (s *Server) handleGetTask(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodGet {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    id := 0
    fmt.Sscanf(r.URL.Query().Get("id"), "%d", &id)

    task, err := s.store.GetTask(id)
    if err != nil {
        http.Error(w, err.Error(), http.StatusNotFound)
        return
    }

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(task)
}
登入後複製

單元測試

以下是 TaskStore 的一些單元測試(用 Ginkgo 寫):

package main

import (
    "log"
    "net/http"
)

func main() {
    store := NewTaskStore()
    server := &Server{store: store}
    http.HandleFunc("/task/create", server.handleCreateTask)
    http.HandleFunc("/task/get", server.handleGetTask)

    log.Printf("Starting server on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}
登入後複製
go build -o taskapi *.go
./taskapi
2024/11/14 07:03:48 Starting server on :8080
登入後複製

在 Emacs 中,我將呼叫 ginkgo-run-this-container,如以下螢幕截圖所示:

Mastering Golang Debugging in Emacs

使用 Delve 和 Dape 進行基本調試

為了除錯我們的任務 API,我們有以下方法:

  • 我們可以直接啟動應用程式並調試它
  • 我們可以附加到正在運行的進程
  • 我們可以附加到正在運行的偵錯會話

以下是不同請求類型的選項:

請求 模式 必填 可選 標題>
request mode required optional
launch debug program dlvCwd, env, backend, args, cwd, buildFlags, output, noDebug
test program dlvCwd, env, backend, args, cwd, buildFlags, output, noDebug
exec program dlvCwd, env, backend, args, cwd, noDebug
core program, corefilePath dlvCwd, env
replay traceDirPath dlvCwd, env
attach local processId backend
remote
啟動 調試 程式 dlvCwd、env、後端、args、cwd、buildFlags、輸出、noDebug 測試 程式 dlvCwd、env、後端、args、cwd、buildFlags、輸出、noDebug 執行 程式 dlvCwd、env、後端、args、cwd、noDebug 核心 程序,核心檔案路徑 dlvCwd,環境 重播 traceDirPath dlvCwd,環境 附加 本地 進程ID 後端 遠端 表>

設定檔 1:啟動應用程式

這是我們的第一個 .dir-locals.el 偵錯設定檔:

(use-package dape
  :straight t
  :config
  ;; Pulse source line (performance hit)
  (add-hook 'dape-display-source-hook 'pulse-momentary-highlight-one-line)

  ;; To not display info and/or buffers on startup
  ;; (remove-hook 'dape-start-hook 'dape-info)
  (remove-hook 'dape-start-hook 'dape-repl))
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

?您可能希望對 command-cwd 使用不同的值。就我而言,我想在目前不是專案的目錄中啟動調試器。 default-directory 是一個變量,它保存目前所在緩衝區的工作目錄。

開始調試:

  • 運行 dape-in​​fo 顯示偵錯資訊

Mastering Golang Debugging in Emacs

  • 使用 dape-breakpoint-toggle 建立斷點:

Mastering Golang Debugging in Emacs

使用此設定檔啟動偵錯器後,您應該在 dape-repl 緩衝區中看到:

(use-package go-mode
  :straight t
  :mode "\.go\'"
  :hook ((before-save . gofmt-before-save))
  :bind (:map go-mode-map
              ("M-?" . godoc-at-point)
              ("M-." . xref-find-definitions)
              ("M-_" . xref-find-references)
              ;; ("M-*" . pop-tag-mark) ;; Jump back after godef-jump
              ("C-c m r" . go-run))
  :custom
  (gofmt-command "goimports"))
登入後複製
登入後複製
登入後複製
登入後複製

請注意,我們沒有指定任何要偵錯的二進位檔案/檔案(我們在 .dir-locals.el 中有 :program ".")。 delve 將在啟動應用程式之前自動建置二進位檔案:

# Install Delve
go install github.com/go-delve/delve/cmd/dlv@latest

# Install gopls
go install golang.org/x/tools/gopls@latest
登入後複製
登入後複製
登入後複製
登入後複製

設定檔 2:連接到外部偵錯器

讓我們新增一個設定檔以連接到現有的偵錯會話:

go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
go install github.com/onsi/ginkgo/v2/ginkgo@latest

go install -v golang.org/x/tools/cmd/godoc@latest
go install -v golang.org/x/tools/cmd/goimports@latest
go install -v github.com/stamblerre/gocode@latest
go install -v golang.org/x/tools/cmd/gorename@latest
go install -v golang.org/x/tools/cmd/guru@latest
go install -v github.com/cweill/gotests/...@latest

go install -v github.com/davidrjenni/reftools/cmd/fillstruct@latest
go install -v github.com/fatih/gomodifytags@latest
go install -v github.com/godoctor/godoctor@latest
go install -v github.com/haya14busa/gopkgs/cmd/gopkgs@latest
go install -v github.com/josharian/impl@latest
go install -v github.com/rogpeppe/godef@latest
登入後複製
登入後複製
登入後複製
登入後複製

現在讓我們在 CLI 上啟動 偵錯器

(use-package ginkgo
  :straight (:type git :host github :repo "garslo/ginkgo-mode")
  :init
  (setq ginkgo-use-pwd-as-test-dir t
        ginkgo-use-default-keys t))

(use-package gotest
  :straight t
  :after go-mode
  :bind (:map go-mode-map
              ("C-c t f" . go-test-current-file)
              ("C-c t t" . go-test-current-test)
              ("C-c t j" . go-test-current-project)
              ("C-c t b" . go-test-current-benchmark)
              ("C-c t c" . go-test-current-coverage)
              ("C-c t x" . go-run)))

(use-package go-guru
  :straight t
  :hook
  (go-mode . go-guru-hl-identifier-mode))

(use-package go-projectile
  :straight t
  :after (projectile go-mode))

(use-package flycheck-golangci-lint
  :straight t
  :hook
  (go-mode . flycheck-golangci-lint-setup))

(use-package go-eldoc
  :straight t
  :hook
  (go-mode . go-eldoc-setup))

(use-package go-tag
  :straight t
  :bind (:map go-mode-map
              ("C-c t a" . go-tag-add)
              ("C-c t r" . go-tag-remove))
  :init (setq go-tag-args (list "-transform" "camelcase")))

(use-package go-fill-struct
  :straight t)

(use-package go-impl
  :straight t)

(use-package go-playground
  :straight t)
登入後複製
登入後複製
登入後複製
登入後複製

現在在 Emacs 中,您可以啟動 dape 並選擇 go-attach-taskapi 設定檔:

Mastering Golang Debugging in Emacs

設定檔 3:附加到正在執行的進程

在這種情況下,應用程式已經正在運行,但您想要附加偵錯器到它。首先啟動應用程式:

{
    "name": "Launch file",
    "type": "go",
    "request": "launch",
    "mode": "auto",
    "program": "${file}"
}
登入後複製
登入後複製

找出其進程ID (PID):

taskapi/
├── go.mod
├── go.sum
├── main.go
├── task_store.go
└── task_test.go
登入後複製
登入後複製

讓我們新增另一個偵錯設定檔:

import (
    "fmt"
)

type Task struct {
    ID          int    `json:"id"`
    Title       string `json:"title"`
    Description string `json:"description"`
    Done        bool   `json:"done"`
}
登入後複製
登入後複製

我們需要一個輔助函數:

type TaskStore struct {
    tasks  map[int]Task
    nextID int
}

func NewTaskStore() *TaskStore {
    return &TaskStore{
        tasks:  make(map[int]Task),
        nextID: 1,
    }
}
登入後複製
登入後複製

Mastering Golang Debugging in Emacs

現在我啟動偵錯器:

Mastering Golang Debugging in Emacs

如果我現在發送像這樣的 POST 請求:

// CreateTask stores a given Task internally
func (ts *TaskStore) CreateTask(task Task) Task {
    task.ID = ts.nextID
    ts.tasks[task.ID] = task
    ts.nextID++
    return task
}

// GetTask retrieves a Task by ID
func (ts *TaskStore) GetTask(id int) (Task, error) {
    task, exists := ts.tasks[id]
    if !exists {
        return Task{}, fmt.Errorf("task with id %d not found", id)
    }
    return task, nil
}

// UpdateTask updates task ID with a new Task object
func (ts *TaskStore) UpdateTask(id int, task Task) error {
    if _, exists := ts.tasks[id]; !exists {
        return fmt.Errorf("task with id %d not found", id)
    }
    task.ID = id
    ts.tasks[id] = task
    return nil
}
登入後複製
登入後複製

偵錯器應在設定的斷點處自動停止:

Mastering Golang Debugging in Emacs

調試 Ginkgo 測試

能夠在 Golang 中除錯測試至關重要。為了執行 ginkgo 測試,我使用 ginkgo-mode,它具有以下功能:

Mastering Golang Debugging in Emacs

Mastering Golang Debugging in Emacs

作為輸出,我得到:

(use-package dape
  :straight t
  :config
  ;; Pulse source line (performance hit)
  (add-hook 'dape-display-source-hook 'pulse-momentary-highlight-one-line)

  ;; To not display info and/or buffers on startup
  ;; (remove-hook 'dape-start-hook 'dape-info)
  (remove-hook 'dape-start-hook 'dape-repl))
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

銀杏的 Dape 配置

這是調試 Ginkgo 測試的基本配置:

(use-package go-mode
  :straight t
  :mode "\.go\'"
  :hook ((before-save . gofmt-before-save))
  :bind (:map go-mode-map
              ("M-?" . godoc-at-point)
              ("M-." . xref-find-definitions)
              ("M-_" . xref-find-references)
              ;; ("M-*" . pop-tag-mark) ;; Jump back after godef-jump
              ("C-c m r" . go-run))
  :custom
  (gofmt-command "goimports"))
登入後複製
登入後複製
登入後複製
登入後複製

如果我選擇 go-test-ginkgo 調試配置文件,我應該能夠調試測試:

Mastering Golang Debugging in Emacs

現在配置非常靜態,因此您無法預先選擇單元測試/容器。我們需要以某種方式讓參數 -ginkgo.focus 動態化:

# Install Delve
go install github.com/go-delve/delve/cmd/dlv@latest

# Install gopls
go install golang.org/x/tools/gopls@latest
登入後複製
登入後複製
登入後複製
登入後複製

Mastering Golang Debugging in Emacs

之後,如果我查看 dape-configs 變量,我應該會看到這個值:

go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
go install github.com/onsi/ginkgo/v2/ginkgo@latest

go install -v golang.org/x/tools/cmd/godoc@latest
go install -v golang.org/x/tools/cmd/goimports@latest
go install -v github.com/stamblerre/gocode@latest
go install -v golang.org/x/tools/cmd/gorename@latest
go install -v golang.org/x/tools/cmd/guru@latest
go install -v github.com/cweill/gotests/...@latest

go install -v github.com/davidrjenni/reftools/cmd/fillstruct@latest
go install -v github.com/fatih/gomodifytags@latest
go install -v github.com/godoctor/godoctor@latest
go install -v github.com/haya14busa/gopkgs/cmd/gopkgs@latest
go install -v github.com/josharian/impl@latest
go install -v github.com/rogpeppe/godef@latest
登入後複製
登入後複製
登入後複製
登入後複製

在 dape-repl 緩衝區中啟動偵錯器(使用以偵錯為中心的測試設定檔)後,我得到:

(use-package ginkgo
  :straight (:type git :host github :repo "garslo/ginkgo-mode")
  :init
  (setq ginkgo-use-pwd-as-test-dir t
        ginkgo-use-default-keys t))

(use-package gotest
  :straight t
  :after go-mode
  :bind (:map go-mode-map
              ("C-c t f" . go-test-current-file)
              ("C-c t t" . go-test-current-test)
              ("C-c t j" . go-test-current-project)
              ("C-c t b" . go-test-current-benchmark)
              ("C-c t c" . go-test-current-coverage)
              ("C-c t x" . go-run)))

(use-package go-guru
  :straight t
  :hook
  (go-mode . go-guru-hl-identifier-mode))

(use-package go-projectile
  :straight t
  :after (projectile go-mode))

(use-package flycheck-golangci-lint
  :straight t
  :hook
  (go-mode . flycheck-golangci-lint-setup))

(use-package go-eldoc
  :straight t
  :hook
  (go-mode . go-eldoc-setup))

(use-package go-tag
  :straight t
  :bind (:map go-mode-map
              ("C-c t a" . go-tag-add)
              ("C-c t r" . go-tag-remove))
  :init (setq go-tag-args (list "-transform" "camelcase")))

(use-package go-fill-struct
  :straight t)

(use-package go-impl
  :straight t)

(use-package go-playground
  :straight t)
登入後複製
登入後複製
登入後複製
登入後複製

?請注意,僅運行了「5 個規格中的 1 個」(❶),這表示 ginkgo 只專注於我們指定的容器 (❷)。

最佳實踐和技巧

透過我的除錯經驗,我開始欣賞一些最佳實踐:

  • 使用版本控制進行調試配置
  • 在 .dir-locals.el 中維護調試配置
  • 使用有意義的名稱進行設定
  • 建立特定於專案的偵錯輔助函數
  • 在本地進行自訂(特定於緩衝區)

資源和參考

  • vscode-go/docs/debugging.md at master · golang/vscode-go
  • 直接支援 delve/dlv dap-mode · Issue #318 · emacs-lsp/dap-mode
  • Dape GitHub 儲存庫
  • 深入調試器
  • Eglot 文件
  • Ginkgo 測試框架

以上是掌握 Emacs 中的 Golang 調試的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Debian OpenSSL有哪些漏洞 Debian OpenSSL有哪些漏洞 Apr 02, 2025 am 07:30 AM

OpenSSL,作為廣泛應用於安全通信的開源庫,提供了加密算法、密鑰和證書管理等功能。然而,其歷史版本中存在一些已知安全漏洞,其中一些危害極大。本文將重點介紹Debian系統中OpenSSL的常見漏洞及應對措施。 DebianOpenSSL已知漏洞:OpenSSL曾出現過多個嚴重漏洞,例如:心臟出血漏洞(CVE-2014-0160):該漏洞影響OpenSSL1.0.1至1.0.1f以及1.0.2至1.0.2beta版本。攻擊者可利用此漏洞未經授權讀取服務器上的敏感信息,包括加密密鑰等。

Beego ORM中如何指定模型關聯的數據庫? Beego ORM中如何指定模型關聯的數據庫? Apr 02, 2025 pm 03:54 PM

在BeegoORM框架下,如何指定模型關聯的數據庫?許多Beego項目需要同時操作多個數據庫。當使用Beego...

從前端轉型後端開發,學習Java還是Golang更有前景? 從前端轉型後端開發,學習Java還是Golang更有前景? Apr 02, 2025 am 09:12 AM

後端學習路徑:從前端轉型到後端的探索之旅作為一名從前端開發轉型的後端初學者,你已經有了nodejs的基礎,...

在Go語言中使用Redis Stream實現消息隊列時,如何解決user_id類型轉換問題? 在Go語言中使用Redis Stream實現消息隊列時,如何解決user_id類型轉換問題? Apr 02, 2025 pm 04:54 PM

Go語言中使用RedisStream實現消息隊列時類型轉換問題在使用Go語言與Redis...

GoLand中自定義結構體標籤不顯示怎麼辦? GoLand中自定義結構體標籤不顯示怎麼辦? Apr 02, 2025 pm 05:09 PM

GoLand中自定義結構體標籤不顯示怎麼辦?在使用GoLand進行Go語言開發時,很多開發者會遇到自定義結構體標籤在�...

Go語言中用於浮點數運算的庫有哪些? Go語言中用於浮點數運算的庫有哪些? Apr 02, 2025 pm 02:06 PM

Go語言中用於浮點數運算的庫介紹在Go語言(也稱為Golang)中,進行浮點數的加減乘除運算時,如何確保精度是�...

Go的爬蟲Colly中Queue線程的問題是什麼? Go的爬蟲Colly中Queue線程的問題是什麼? Apr 02, 2025 pm 02:09 PM

Go爬蟲Colly中的Queue線程問題探討在使用Go語言的Colly爬蟲庫時,開發者常常會遇到關於線程和請求隊列的問題。 �...

如何在Debian上配置MongoDB自動擴容 如何在Debian上配置MongoDB自動擴容 Apr 02, 2025 am 07:36 AM

本文介紹如何在Debian系統上配置MongoDB實現自動擴容,主要步驟包括MongoDB副本集的設置和磁盤空間監控。一、MongoDB安裝首先,確保已在Debian系統上安裝MongoDB。使用以下命令安裝:sudoaptupdatesudoaptinstall-ymongodb-org二、配置MongoDB副本集MongoDB副本集確保高可用性和數據冗餘,是實現自動擴容的基礎。啟動MongoDB服務:sudosystemctlstartmongodsudosys

See all articles