Rumah > pembangunan bahagian belakang > Golang > Menguasai Penyahpepijatan Golang dalam Emacs

Menguasai Penyahpepijatan Golang dalam Emacs

Linda Hamilton
Lepaskan: 2024-12-02 11:56:09
asal
215 orang telah melayarinya

pengenalan

Sejak saya mula membangun di Golang, saya tidak begitu menggunakan debugger. Sebaliknya saya secara naif menambah pernyataan fmt.Cetak di mana-mana untuk mengesahkan kod saya ?. Walaupun kenyataan cetak dan log mungkin juga merupakan naluri penyahpepijatan pertama anda, ia sering gagal apabila berurusan dengan asas kod yang besar dan kompleks, dengan gelagat masa jalan yang canggih dan (sudah tentu!) isu konkurensi kompleks yang kelihatan mustahil untuk dihasilkan semula.

Selepas mula mengerjakan projek yang lebih kompleks (seperti ini: https://github.com/cloudoperators/heureka) saya terpaksa memaksa diri saya untuk melihat dengan lebih mendalam pada delve (penyahpepijat Golang) dan melihat apa yang ditawarkan oleh Emacs berinteraksi dengannya. Walaupun ekosistem Go menawarkan alat penyahpepijatan yang sangat baik, menyepadukannya ke dalam aliran kerja pembangunan yang selesa boleh menjadi mencabar.

Dalam siaran ini saya akan menghuraikan gabungan hebat Emacs, Delve dan dape. Bersama-sama, alatan ini mencipta pengalaman penyahpepijatan yang meniru (dan selalunya mengatasi) IDE tradisional, sambil mengekalkan fleksibiliti dan kebolehlanjutan yang Emacs terkenal.

Inilah yang anda boleh jangkakan:

  • Sediakan dan konfigurasikan Delve dengan dape
  • Nyahpepijat kedua-dua aplikasi standard dan ujian Ginkgo (inilah yang saya gunakan pada masa ini?)
  • Optimumkan aliran kerja penyahpepijatan anda dengan penyesuaian khusus Emacs

Menyediakan Persekitaran Pembangunan

Dalam siaran ini saya menganggap anda sudah mempunyai beberapa pengalaman Emacs dan kini cara mengkonfigurasi pakej dan menulis coretan Elisp kecil. Saya secara peribadi menggunakan straight.el sebagai pengurus pakej, minimal-emacs.d sebagai konfigurasi Emacs vanila minimum (bersama-sama dengan penyesuaian saya sendiri), dape sebagai klien penyesuai nyahpepijat dan eglot sebagai klien LSP saya.

Pakej Emacs Diperlukan

Untuk pengguna Emacs 29, eglot terbina dalam. Lihat mengkonfigurasi eglot untuk gopls dan beberapa tetapan gopls yang lebih maju. Kita tambah dape dulu:

(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))
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dan mod pergi:

(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"))
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Memasang Alat Go yang Diperlukan

Pasang Delve dan gopls, pelayan LSP:

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

# Install gopls
go install golang.org/x/tools/gopls@latest
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Selain itu, saya mempunyai banyak alatan lain yang saya gunakan dari semasa ke semasa:

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
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kemudian anda perlu mengkonfigurasi pakej Emacs yang sepadan:

(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)
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Konfigurasi Dape

Tiada sebab tertentu mengapa saya menggunakan dape sebagai ganti dap. Apabila saya masih menggunakan MinEmacs ia adalah sebahagian daripadanya dan saya baru terbiasa dengannya. Seperti yang dinyatakan dalam dokumentasi:

  • Dape tidak menyokong fail launch.json, jika konfigurasi setiap projek diperlukan gunakan dir-locals dan dape-command.
  • Dape meningkatkan ergonomik dalam penimbal mini dengan membenarkan pengguna mengubah suai atau menambah entri PLIST pada konfigurasi sedia ada menggunakan pilihan.
  • Tiada sihir, tiada pembolehubah khas seperti ${workspaceFolder}. Sebaliknya, fungsi dan pembolehubah diselesaikan sebelum memulakan sesi baharu.
  • Cuba untuk membayangkan bagaimana konfigurasi penyesuai nyahpepijat akan dilaksanakan dalam Emacs jika vscode tidak pernah wujud.

Jika anda pernah bekerja dengan VSCode, anda sudah tahu bahawa ia menggunakan launch.json untuk menyimpan profil penyahpepijatan yang berbeza:

(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))
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Anda mempunyai medan/sifat berbeza yang mengikut halaman ini anda boleh tweak dalam konfigurasi penyahpepijatan anda:

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)

Contoh Permohonan

Sekarang mari kita praktikkan pengetahuan kita dengan menyahpepijat aplikasi sebenar yang melaksanakan API REST.

Struktur Projek

Contoh kami ialah REST API untuk pengurusan tugasan dengan struktur berikut:

(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))
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Komponen Teras

Mari kita lihat komponen teras.

Tugas mewakili model domain teras kami:

(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"))
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Stor Tugas mengendalikan operasi data dalam memori kami:

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

# Install gopls
go install golang.org/x/tools/gopls@latest
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

API REST

API mendedahkan titik akhir berikut:

  • POST /task/create - Mencipta tugasan baharu
  • DAPATKAN /task/get?id= - Mendapat semula tugas dengan 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
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Pelayan

Berikut ialah pelaksanaan pelayan:

(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)
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Jom tengok fungsi utama kami:

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

Membina aplikasi

Mari mulakan pelayan:

taskapi/
├── go.mod
├── go.sum
├── main.go
├── task_store.go
└── task_test.go
Salin selepas log masuk
Salin selepas log masuk

Kini daripada terminal lain buat tugas baharu:

import (
    "fmt"
)

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

Jawapan:

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

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

Mari kita lihat sama ada kita boleh mengambilnya:

// 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
}
Salin selepas log masuk
Salin selepas log masuk

Jawapan:

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)
}
Salin selepas log masuk

Ujian unit

Di bawah ialah beberapa ujian unit (ditulis dalam Ginkgo) untuk Kedai Tugas:

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))
}
Salin selepas log masuk
go build -o taskapi *.go
./taskapi
2024/11/14 07:03:48 Starting server on :8080
Salin selepas log masuk

Dalam Emacs saya kemudiannya akan memanggil ginkgo-run-this-container seperti yang ditunjukkan dalam tangkapan skrin ini:

Mastering Golang Debugging in Emacs

Penyahpepijatan Asas dengan Delve dan Dape

Untuk menyahpepijat API Tugas kami, kami mempunyai pendekatan berikut:

  • kami boleh melancarkan aplikasi secara terus dan nyahpepijat
  • kita boleh lampirkan pada proses yang sedang berjalan
  • kita boleh lampirkan pada sesi penyahpepijatan yang sedang berjalan

Berikut ialah pilihan untuk jenis permintaan yang berbeza:

permintaan mod diperlukan pilihan
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
pelancaran nyahpepijat program dlvCwd, env, backend, args, cwd, buildFlags, output, noDebug ujian program dlvCwd, env, backend, args, cwd, buildFlags, output, noDebug eksekusi program dlvCwd, env, backend, args, cwd, noDebug teras program, corefilePath dlvCwd, env main semula traceDirPath dlvCwd, env lampirkan tempatan processId belakang jauh

Profil 1: Lancarkan aplikasi

Berikut ialah profil penyahpepijatan pertama kami untuk .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))
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

? Anda mungkin mahu menggunakan nilai yang berbeza untuk perintah-cwd. Dalam kes saya, saya mahu memulakan penyahpepijat dalam direktori yang pada masa ini bukan projek. default-directory ialah pembolehubah yang menyimpan direktori kerja untuk penimbal semasa yang anda sedang masuk.

Mulakan nyahpepijat:

  • Jalankan dape-info untuk menunjukkan maklumat penyahpepijatan

Mastering Golang Debugging in Emacs

  • Buat titik putus menggunakan dape-breakpoint-toggle:

Mastering Golang Debugging in Emacs

Selepas memulakan penyahpepijat dengan profil ini, anda seharusnya melihat dalam penimbal 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"))
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Perhatikan bahawa kami tidak menentukan sebarang perduaan/fail untuk nyahpepijat (kami mempunyai :program "." dalam .dir-locals.el). delve akan secara automatik membina binari sebelum ia melancarkan aplikasi:

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

# Install gopls
go install golang.org/x/tools/gopls@latest
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Profil 2: Lampirkan pada penyahpepijat luaran

Mari tambahkan profil untuk menyambung ke sesi penyahpepijatan sedia ada:

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
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Sekarang mari kita mulakan penyahpepijat pada 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)
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kini dalam Emacs anda boleh melancarkan dape dan pilih profil go-attach-taskapi:

Mastering Golang Debugging in Emacs

Profil 3: Lampirkan pada proses yang sedang berjalan

Dalam senario ini aplikasi sudah berjalan tetapi anda mahu lampirkan penyahpepijat padanya. Mula-mula lancarkan aplikasi:

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

Ketahui ID prosesnya (PID):

taskapi/
├── go.mod
├── go.sum
├── main.go
├── task_store.go
└── task_test.go
Salin selepas log masuk
Salin selepas log masuk

Mari tambah satu lagi profil nyahpepijat:

import (
    "fmt"
)

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

Kami memerlukan fungsi pembantu:

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

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

Mastering Golang Debugging in Emacs

Sekarang saya memulakan penyahpepijat:

Mastering Golang Debugging in Emacs

Jika saya menghantar permintaan POST seperti ini:

// 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
}
Salin selepas log masuk
Salin selepas log masuk

Penyahpepijat harus berhenti secara automatik pada titik putus yang ditetapkan:

Mastering Golang Debugging in Emacs

Menyahpepijat Ujian Ginkgo

Keupayaan untuk menyahpepijat ujian di Golang adalah penting. Untuk menjalankan ujian ginkgo saya menggunakan ginkgo-mode yang mempunyai beberapa ciri:

Mastering Golang Debugging in Emacs

Mastering Golang Debugging in Emacs

Dan sebagai output saya dapat:

(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))
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Konfigurasi Dape untuk Ginkgo

Ini ialah konfigurasi asas untuk menyahpepijat ujian 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"))
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Jika saya memilih profil nyahpepijat go-test-ginkgo, saya sepatutnya dapat menyahpepijat ujian:

Mastering Golang Debugging in Emacs

Kini konfigurasi agak statik dan oleh itu anda tidak boleh prapilih ujian unit / bekas. Kita perlu entah bagaimana menjadikan parameter -ginkgo.focus dinamik:

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

# Install gopls
go install golang.org/x/tools/gopls@latest
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Mastering Golang Debugging in Emacs

Selepas itu Jika saya melihat pembolehubah dape-configs, saya akan melihat nilai ini:

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
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Selepas memulakan penyahpepijat (dengan profil ujian fokus-debug) dalam penimbal dape-repl saya mendapat:

(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)
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

?Perhatikan bahawa hanya "1 daripada 5 spesifikasi" (❶) dijalankan, bermakna ginkgo hanya memfokuskan pada bekas yang telah kami tentukan (❷).

Amalan dan Petua Terbaik

Sepanjang pengalaman penyahpepijatan saya, saya telah menghargai beberapa amalan terbaik:

  • Gunakan kawalan versi untuk konfigurasi penyahpepijatan
  • Kekalkan konfigurasi nyahpepijat dalam .dir-locals.el
  • Gunakan nama yang bermakna untuk konfigurasi
  • Buat projek khusus penyahpepijatan fungsi pembantu
  • Buat penyesuaian setempat (khusus penimbal)

Sumber dan Rujukan

  • vscode-go/docs/debugging.md at master · golang/vscode-go
  • sokong delve/dlv dap-mod secara langsung · Isu #318 · emacs-lsp/dap-mode
  • Repositori GitHub Dape
  • Delve Debugger
  • Dokumentasi Eglot
  • Rangka Kerja Pengujian Ginkgo

Atas ialah kandungan terperinci Menguasai Penyahpepijatan Golang dalam Emacs. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan