ホームページ >バックエンド開発 >Golang >Emacs で Golang のデバッグをマスターする

Emacs で Golang のデバッグをマスターする

Linda Hamilton
Linda Hamiltonオリジナル
2024-12-02 11:56:09204ブラウズ

導入

私は Golang で開発を始めて以来、デバッガ を実際には使用しませんでした。代わりに、コードを検証するために fmt.Print ステートメントをどこにでも単純に追加していました。 print ステートメントとログもデバッグの最初の本能かもしれませんが、高度な実行時の動作や (当然のことですが) 再現不可能と思われる複雑な同時実行の問題を伴う、大規模で複雑なコード ベースを扱う場合には不十分なことがよくあります。

より複雑なプロジェクト (次のようなプロジェクト: https://github.com/cloudoperators/heureka) に取り組み始めた後、delve (Golang デバッガー) を詳しく調べて、Emacs が何を提供するのかを確認する必要がありました。それと対話します。 Go エコシステムは優れたデバッグ ツールを提供しますが、それらを快適な開発ワークフローに統合するのは困難な場合があります。

この投稿では、Emacs、Delve、dape の強力な組み合わせについて詳しく説明します。これらのツールを組み合わせることで、Emacs の有名な柔軟性と拡張性を維持しながら、従来の IDE を模倣する (そして多くの場合、それを超える) デバッグ エクスペリエンスが作成されます。

次のことが期待できます:

  • 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 ツールのインストール

LSP サーバーである Delve と gopls をインストールします。

# 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)

データの構成

dap の代わりに dape を使用する特別な理由はありません。私がまだ MinEmacs を使用していたとき、それはその一部であり、それに慣れただけです。ドキュメントに記載されているように:

  • Dape は launch.json ファイルをサポートしていません。プロジェクトごとの構成が必要な場合は、dir-locals と dape-command を使用してください。
  • Dape は、ユーザーがオプションを使用して既存の構成に PLIST エントリを変更または追加できるようにすることで、ミニバッファー内の人間工学を強化します。
  • 魔法や ${workspaceFolder} のような特別な変数はありません。代わりに、関数と変数は新しいセッションを開始する前に解決されます。
  • vscode が存在しなかった場合、デバッグ アダプター設定が Emacs にどのように実装されるかを想像しようとします。

VSCode を使用したことがある方は、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

REST 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))

Ginkgo の 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 バッファーでデバッガーを (debug-focused-test プロファイルを使用して) 起動すると、次の結果が得られます。

(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 · golang/vscode-go
  • delve/dlv dap-mode を直接サポート · 問題 #318 · emacs-lsp/dap-mode
  • Dape GitHub リポジトリ
  • Delve デバッガー
  • Eglot ドキュメント
  • Ginkgo テスト フレームワーク

以上がEmacs で Golang のデバッグをマスターするの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。