Gopls:在 Emacs 中使用
安装 gopls
要在 Emacs 中使用 gopls
,您必须首先 安装 gopls
可执行文件,并确保包含生成二进制文件的目录(即 $(go env GOBIN)
或 $(go env GOPATH)/bin
)已添加到您的 PATH
中。
选择 Emacs LSP 客户端
要在 Emacs 中使用 gopls
,您需要选择并安装一个 Emacs LSP 客户端包。两个流行的客户端包是 LSP Mode 和 Eglot。
LSP Mode 采用“开箱即用”的方法,集成了许多功能,并且 lsp-mode
本身提供了许多额外的行为。
Eglot 采用最小侵入式的方法,专注于与其他成熟的包进行顺畅集成。它提供了一些自己的 eglot-
命令,但默认情况下不提供额外的键绑定。
选择好要使用的客户端后,请按照软件包说明进行安装:参见 Eglot 1-2-3 或 LSP 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 组织导入
gopls
将 goimports
的导入组织功能作为 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 下找到。