gopls
To use gopls
with Emacs, you must first install the gopls
binary and ensure that the directory containing the resulting binary (either $(go env GOBIN)
or $(go env GOPATH)/bin
) is in your PATH
.
To use gopls
with Emacs, you will need to choose and install an Emacs LSP client package. Two popular client packages are LSP Mode and Eglot.
LSP Mode takes a batteries-included approach, with many integrations enabled “out of the box” and several additional behaviors provided by lsp-mode
itself.
Eglot takes a minimally-intrusive approach, focusing on smooth integration with other established packages. It provides a few of its own eglot-
commands but no additional keybindings by default.
Once you have selected which client you want to use, install it per the packages instructions: see Eglot 1-2-3 or LSP Mode Installation.
Both Eglot and LSP Mode can integrate with popular packages in the Emacs ecosystem:
xref
package provides cross-references.completion-at-point
).Eglot provides documentation using the built-in ElDoc minor mode, while LSP Mode by default provides documentation using its own lsp-ui
mode.
Eglot by default locates the project root using the [project
] package. In LSP Mode, this behavior can be configured using the lsp-auto-guess-root
setting.
.emacs
(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)
gopls
via LSP ModeSee settings for information about available gopls settings.
Stable gopls settings have corresponding configuration variables in lsp-mode
. For example, (setq lsp-gopls-use-placeholders nil)
will disable placeholders in completion snippets. See lsp-go
for a list of available variables.
Experimental settings can be configured via lsp-register-custom-settings
:
(lsp-register-custom-settings '(("gopls.completeUnimported" t t) ("gopls.staticcheck" t t)))
Note that after changing settings you must restart gopls using e.g. M-x lsp-restart-workspace
.
project
for Go modules in .emacs
Eglot uses the built-in project
package to identify the LSP workspace for a newly-opened buffer. The project
package does not natively know about GOPATH
or Go modules. Fortunately, you can give it a custom hook to tell it to look for the nearest parent go.mod
file (that is, the root of the Go module) as the project root.
(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
;; 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 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)
Use M-x eglot-upgrade-eglot
to upgrade to the latest version of Eglot.
gopls
via EglotSee settings for information about available gopls settings.
LSP server settings are controlled by the eglot-workspace-configuration
variable, which can be set either globally in .emacs
or in a .dir-locals.el
file in the project root.
.emacs
:
(setq-default eglot-workspace-configuration '((:gopls . ((staticcheck . t) (matcher . "CaseSensitive")))))
.dir-locals.el
:
((nil (eglot-workspace-configuration . ((gopls . ((staticcheck . t) (matcher . "CaseSensitive")))))))
gopls
provides the import-organizing functionality of goimports
as an LSP code action, which you can invoke as needed by running M-x eglot-code-actions
(or a key of your choice bound to the eglot-code-actions
function) and selecting Organize Imports
at the prompt.
To automatically organize imports before saving, add a hook:
(add-hook 'before-save-hook (lambda () (call-interactively 'eglot-code-action-organize-imports)) nil t)
Common errors:
M-x getenv <RET> PATH <RET>
to see if your PATH is set in Emacs. If not, you can try starting Emacs from your terminal, using [this package][exec-path-from-shell], or moving your shell config from .bashrc
into .profile
and logging out and back in.lsp-mode
, ensure that you are not also enabling eglot
.)*lsp-log*
buffer or run M-x eglot-events-buffer
.#emacs
channel on the Gophers slack.