Maison >développement back-end >Golang >Maîtriser le débogage Golang dans Emacs

Maîtriser le débogage Golang dans Emacs

Linda Hamilton
Linda Hamiltonoriginal
2024-12-02 11:56:09206parcourir

Introduction

Depuis que j'ai commencé à développer en Golang, je n'ai pas vraiment utilisé le débogueur. Au lieu de cela, j'ajoutais naïvement des instructions fmt.Print partout pour valider mon code ?. Bien que les instructions d'impression et les journaux puissent également être votre premier instinct de débogage, ils échouent souvent lorsqu'il s'agit d'une base de code volumineuse et complexe, avec un comportement d'exécution sophistiqué et (bien sûr !) des problèmes de concurrence complexes qui semblent impossibles à reproduire.

Après avoir commencé à travailler sur des projets plus complexes (comme celui-ci : https://github.com/cloudoperators/heureka) j'ai dû me forcer à approfondir delve (le débogueur Golang) et voir ce que propose Emacs interagir avec lui. Bien que l'écosystème Go offre d'excellents outils de débogage, les intégrer dans un flux de développement confortable peut s'avérer difficile.

Dans cet article, je vais élaborer la puissante combinaison d'Emacs, Delve et dape. Ensemble, ces outils créent une expérience de débogage qui imite (et dépasse souvent) les IDE traditionnels, tout en préservant la flexibilité et l'extensibilité qui font la renommée d'Emacs.

Voici ce à quoi vous pouvez vous attendre :

  • Installer et configurer Delve avec dape
  • Déboguer les applications standards et les tests Ginkgo (c'est ce que j'utilise en ce moment ?)
  • Optimisez votre flux de travail de débogage avec des personnalisations spécifiques à Emacs

Configuration de l'environnement de développement

Dans cet article, je suppose que vous avez déjà une certaine expérience avec Emacs et que vous savez maintenant comment configurer des packages et écrire de petits extraits Elisp. J'utilise personnellement Straight.el comme gestionnaire de paquets, minimal-emacs.d comme configuration minimale d'Emacs Vanilla (avec mes propres personnalisations), dape comme client adaptateur de débogage et eglot comme mon client LSP.

Packages Emacs requis

Pour les utilisateurs d'Emacs 29, eglot est intégré. Découvrez la configuration d'eglot pour les gopls et quelques paramètres gopls plus avancés. Nous allons d'abord ajouter 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))

Et go-mode :

(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"))

Installation des outils Go requis

Installez Delve et gopls, le serveur LSP :

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

# Install gopls
go install golang.org/x/tools/gopls@latest

De plus, j'ai un tas d'autres outils que j'utilise de temps en temps :

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

Ensuite, vous devez configurer les packages Emacs correspondants :

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

Configuration du Dape

Il n'y a aucune raison particulière pour laquelle j'utilise du dape au lieu de dap. Quand j'utilisais encore MinEmacs, cela en faisait partie et je m'y suis juste habitué. Comme l'indique la documentation :

  • Dape ne prend pas en charge les fichiers launch.json, si une configuration par projet est nécessaire, utilisez dir-locals et dape-command.
  • Dape améliore l'ergonomie au sein du mini-tampon en permettant aux utilisateurs de modifier ou d'ajouter des entrées PLIST à une configuration existante à l'aide d'options.
  • Pas de magie, pas de variables spéciales comme ${workspaceFolder}. Au lieu de cela, les fonctions et les variables sont résolues avant de démarrer une nouvelle session.
  • Essaye d'imaginer comment les configurations de l'adaptateur de débogage seraient implémentées dans Emacs si vscode n'existait jamais.

Si vous avez déjà travaillé avec VSCode, vous savez déjà qu'il utilise un launch.json pour stocker différents profils de débogage :

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

Vous disposez de différents champs/propriétés que, selon cette page, vous pouvez modifier dans votre configuration de débogage :

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)

Exemple d'application

Mettons maintenant nos connaissances en pratique en déboguant une application réelle implémentant une API REST.

Structure du projet

Notre exemple est une API REST pour la gestion des tâches avec la structure suivante :

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

Composants de base

Jetons un coup d'œil aux composants de base.

La tâche représente notre modèle de domaine principal :

(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"))

Le TaskStore gère nos opérations de données en mémoire :

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

# Install gopls
go install golang.org/x/tools/gopls@latest

API REST

L'API expose les points de terminaison suivants :

  • POST /task/create - Crée une nouvelle tâche
  • GET /task/get?id= - Récupère une tâche par 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

Serveur

Voici l'implémentation du serveur :

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

Regardons notre fonction principale :

{
    "name": "Launch file",
    "type": "go",
    "request": "launch",
    "mode": "auto",
    "program": "${file}"
}

Créer une application

Démarrons le serveur :

taskapi/
├── go.mod
├── go.sum
├── main.go
├── task_store.go
└── task_test.go

Maintenant depuis un autre terminal créez une nouvelle tâche :

import (
    "fmt"
)

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

Réponse :

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

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

Voyons si nous pouvons le récupérer :

// 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
}

Réponse :

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

Tests unitaires

Vous trouverez ci-dessous quelques tests unitaires (écrits en Ginkgo) pour le TaskStore :

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

Dans Emacs, j'appellerais alors ginkgo-run-this-container comme indiqué dans cette capture d'écran :

Mastering Golang Debugging in Emacs

Débogage de base avec Delve et Dape

Afin de déboguer notre API de tâches, nous avons les approches suivantes :

  • on peut lancer l'application directement et la déboguer
  • on peut attacher à un processus en cours d'exécution
  • nous pouvons attacher à une session de débogage en cours

Voici les options pour différents types de demandes :

demande mode obligatoire facultatif ête>
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
lancement débogage programme dlvCwd, env, backend, args, cwd, buildFlags, sortie, noDebug tester programme dlvCwd, env, backend, args, cwd, buildFlags, sortie, noDebug exécutable programme dlvCwd, env, backend, args, cwd, noDebug noyau programme, corefilePath dlvCwd, env rejouer traceDirPath dlvCwd, env joindre local IDprocessus back-end à distance

Profil 1 : Lancer l'application

Voici notre premier profil de débogage pour .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))

? Vous souhaiterez peut-être utiliser une valeur différente pour command-cwd. Dans mon cas, je voulais démarrer le débogueur dans un répertoire qui n'est actuellement pas un projet. default-directory est une variable qui contient le répertoire de travail du tampon actuel dans lequel vous vous trouvez actuellement.

Démarrer le débogage :

  • Exécutez dape-info pour afficher les informations de débogage

Mastering Golang Debugging in Emacs

  • Créez un point d'arrêt à l'aide de dape-breakpoint-toggle :

Mastering Golang Debugging in Emacs

Après avoir démarré le débogueur avec ce profil, vous devriez voir dans le tampon 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"))

Notez que nous n'avons spécifié aucun binaire/fichier à déboguer (nous avions :program "." dans .dir-locals.el). delve construira automatiquement le binaire avant de lancer l'application :

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

# Install gopls
go install golang.org/x/tools/gopls@latest

Profil 2 : attacher à un débogueur externe

Ajoutons un profil pour se connecter à une session de débogage existante :

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

Démarrons maintenant le débogueur sur la 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)

Maintenant dans Emacs, vous pouvez lancer dape et sélectionner le profil go-attach-taskapi :

Mastering Golang Debugging in Emacs

Profil 3 : attacher à un processus en cours d'exécution

Dans ce scénario, l'application est déjà en cours d'exécution mais vous souhaitez y attacher le débogueur. Lancez d’abord l’application :

{
    "name": "Launch file",
    "type": "go",
    "request": "launch",
    "mode": "auto",
    "program": "${file}"
}

Découvrez son ID de processus (PID) :

taskapi/
├── go.mod
├── go.sum
├── main.go
├── task_store.go
└── task_test.go

Ajoutons un autre profil de débogage :

import (
    "fmt"
)

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

Nous aurons besoin d'une fonction d'assistance :

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

Maintenant, je démarre le débogueur :

Mastering Golang Debugging in Emacs

Si j'envoie maintenant une requête POST comme celle-ci :

// 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
}

Le débogueur devrait s'arrêter automatiquement au point d'arrêt défini :

Mastering Golang Debugging in Emacs

Débogage des tests Ginkgo

Être capable de déboguer les tests dans Golang est crucial. Pour exécuter des tests de ginkgo, j'utilise le mode ginkgo qui possède plusieurs fonctionnalités :

Mastering Golang Debugging in Emacs

Mastering Golang Debugging in Emacs

Et en sortie j'obtiens :

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

Configuration Dape pour Ginkgo

Voici la configuration de base pour le débogage des tests 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"))

Si j'ai choisi le profil de débogage go-test-ginkgo, je devrais pouvoir déboguer les tests :

Mastering Golang Debugging in Emacs

Maintenant, la configuration est assez statique et vous ne pouvez donc pas présélectionner le test unitaire/conteneur. Nous devons en quelque sorte rendre le paramètre -ginkgo.focus dynamique :

# 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

Ensuite, si je regarde la variable dape-configs, je devrais voir cette valeur :

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

Après avoir démarré le débogueur (avec le profil debug-focused-test) dans le tampon dape-repl, j'obtiens :

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

?Remarquez que seules "1 des 5 spécifications" (❶) ont été exécutées, ce qui signifie que le ginkgo s'est uniquement concentré sur le conteneur que nous avons spécifié (❷).

Meilleures pratiques et conseils

Tout au long de mon expérience de débogage, j'ai appris à apprécier plusieurs bonnes pratiques :

  • Utiliser le contrôle de version pour le débogage des configurations
  • Maintenir les configurations de débogage dans .dir-locals.el
  • Utilisez des noms significatifs pour les configurations
  • Créer des fonctions d'assistance spécifiques au projet de débogage
  • Faire des personnalisations localement
  • (spécifiques au tampon)

Ressources et références
  • vscode-go/docs/debugging.md chez master · golang/vscode-go
  • supporte directement le mode dap delve/dlv · Numéro 318 · emacs-lsp/dap-mode
  • Dépôt GitHub Dape
  • Débogueur Delve
  • Documentation Eglot
  • Cadre de test Ginkgo

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn