Gopls:在 Emacs 中使用

安裝 gopls

要在 Emacs 中使用 gopls,您必須首先 安裝 gopls 可執行檔案,並確保包含生成二進位制檔案的目錄(即 $(go env GOBIN)$(go env GOPATH)/bin)已新增到您的 PATH 中。

選擇 Emacs LSP 客戶端

要在 Emacs 中使用 gopls,您需要選擇並安裝一個 Emacs LSP 客戶端包。兩個流行的客戶端包是 LSP ModeEglot

LSP Mode 採用“開箱即用”的方法,集成了許多功能,並且 lsp-mode 本身提供了許多額外的行為。

Eglot 採用最小侵入式的方法,專注於與其他成熟的包進行順暢整合。它提供了一些自己的 eglot- 命令,但預設情況下不提供額外的鍵繫結。

選擇好要使用的客戶端後,請按照軟體包說明進行安裝:參見 Eglot 1-2-3LSP Mode 安裝

通用配置

Eglot 和 LSP Mode 都可以與 Emacs 生態系統中流行的包整合

  • 內建的 xref 包提供交叉引用。
  • 內建的 Flymake 包提供即時診斷疊加。
  • Company 模式顯示程式碼補全候選(比內建的 completion-at-point 提供更豐富的 UI)。

Eglot 使用內建的 ElDoc 迷你模式提供文件,而 LSP Mode 預設使用其自己的 lsp-ui 模式提供文件。

Eglot 預設使用 [project] 包定位專案根目錄。在 LSP Mode 中,可以透過 lsp-auto-guess-root 設定來配置此行為。

配置 LSP Mode

.emacs 中載入 LSP Mode

(require 'lsp-mode)
(add-hook 'go-mode-hook #'lsp-deferred)

;; Set up before-save hooks to format buffer and add/delete imports.
;; Make sure you don't have other gofmt/goimports hooks enabled.
(defun lsp-go-install-save-hooks ()
  (add-hook 'before-save-hook #'lsp-format-buffer t t)
  (add-hook 'before-save-hook #'lsp-organize-imports t t))
(add-hook 'go-mode-hook #'lsp-go-install-save-hooks)

透過 LSP Mode 配置 gopls

有關可用的 gopls 設定資訊,請參見 設定

穩定的 gopls 設定在 lsp-mode 中有相應的配置變數。例如,(setq lsp-gopls-use-placeholders nil) 將停用補全片段中的佔位符。有關可用變數列表,請參見 lsp-go

可以透過 lsp-register-custom-settings 配置實驗性設定

(lsp-register-custom-settings
 '(("gopls.completeUnimported" t t)
   ("gopls.staticcheck" t t)))

請注意,更改設定後,您必須使用例如 M-x lsp-restart-workspace 來重新啟動 gopls。

配置 Eglot

.emacs 中為 Go modules 配置 project

Eglot 使用內建的 project 包來識別新開啟的緩衝區的 LSP 工作區。project 包本身不瞭解 GOPATH 或 Go modules。幸運的是,您可以為其提供一個自定義鉤子,告訴它查詢最近的父級 go.mod 檔案(即 Go 模組的根目錄)作為專案根目錄。

(require 'project)

(defun project-find-go-module (dir)
  (when-let ((root (locate-dominating-file dir "go.mod")))
    (cons 'go-module root)))

(cl-defmethod project-root ((project (head go-module)))
  (cdr project))

(add-hook 'project-find-functions #'project-find-go-module)

.emacs 中載入 Eglot

;; Optional: load other packages before eglot to enable eglot integrations.
(require 'company)
(require 'yasnippet)

(require 'go-mode)
(require 'eglot)
(add-hook 'go-mode-hook 'eglot-ensure)

;; Optional: install eglot-format-buffer as a save hook.
;; The depth of -10 places this before eglot's willSave notification,
;; so that notification reports the actual contents that will be saved.
(defun eglot-format-buffer-before-save ()
  (add-hook 'before-save-hook #'eglot-format-buffer -10 t))
(add-hook 'go-mode-hook #'eglot-format-buffer-before-save)

使用 M-x eglot-upgrade-eglot 升級到最新版本的 Eglot。

透過 Eglot 配置 gopls

有關可用的 gopls 設定資訊,請參見 設定

LSP 伺服器設定由 eglot-workspace-configuration 變數控制,該變數可以在 .emacs 中全域性設定,也可以在專案根目錄的 .dir-locals.el 檔案中設定。

.emacs:

(setq-default eglot-workspace-configuration
    '((:gopls .
        ((staticcheck . t)
         (matcher . "CaseSensitive")))))

.dir-locals.el:

((nil (eglot-workspace-configuration . ((gopls . ((staticcheck . t)
                          (matcher . "CaseSensitive")))))))

使用 Eglot 組織匯入

goplsgoimports 的匯入組織功能作為 LSP 程式碼操作提供,您可以透過執行 M-x eglot-code-actions(或繫結到 eglot-code-actions 函式但您選擇的任意鍵)並在提示時選擇 Organize Imports 來按需呼叫它。

要在儲存前自動組織匯入,請新增一個鉤子

(add-hook 'before-save-hook
    (lambda ()
        (call-interactively 'eglot-code-action-organize-imports))
    nil t)

故障排除

常見錯誤

  • 當 Emacs 提示您輸入專案資料夾時,如果您正在使用 modules,則必須選擇模組的根資料夾(即包含“go.mod”的目錄)。如果您使用 GOPATH,請將您的 $GOPATH 選為您的資料夾。
  • Emacs 必須正確設定您的環境(PATH、GOPATH 等)。您可以執行 M-x getenv <RET> PATH <RET> 來檢視您的 PATH 是否在 Emacs 中設定。如果未設定,您可以嘗試從終端啟動 Emacs,使用 [此包][exec-path-from-shell],或將您的 shell 配置從 .bashrc 移動到 .profile 並登出後重新登入。
  • 確保只安裝了一個 LSP 客戶端模式。(例如,如果使用 lsp-mode,請確保您沒有同時啟用 eglot。)
  • 檢視 *lsp-log* 緩衝區中的錯誤,或執行 M-x eglot-events-buffer
  • 在 Gophers slack 的 #emacs 頻道尋求幫助。Gophers slack

本文件的原始碼可以在 golang.org/x/tools/gopls/doc 下找到。