go-mode.el: Go editing, formatting, and navigation in Emacs
Emacs mode for the Go programming language
At a glance
- What is it?
- go-mode.el is an Emacs editing mode for Go source files, with direct support for gofmt, godoc, imports, coverage, and godef. It suits Emacs users who want language commands without replacing the editor, while gopls through lsp-mode offers a different language-server architecture.
- Who is it for?
- Adopt go-mode.el when working in Emacs and needing a dedicated Go editing mode with gofmt, godoc, import, and coverage commands. Do not choose it alone when your requirement is type-aware completion, diagnostics, renaming, or other language-server behavior that the README assigns to gopls.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 148 days ago.
- What is it written in?
- Mainly Emacs Lisp, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Star history
- dominikh/go-mode.el1,456 ★ · +0
| Repository | 2026-10-16 | 2026-10-24 |
|---|---|---|
| dominikh/go-mode.el | 1.5k | 1.5k |
0 Stars in the last 8 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Why go-mode.el serves Go developers in Emacs
go-mode.el addresses a specific distribution problem: Go editor integration is no longer included with the Go distribution. The README says the project is a complete rewrite of the older go-mode that shipped with Go 1.0.3 and earlier and was part of Go through Go 1.3. Since Go 1.4, the repository is described as the canonical location for this Emacs mode.
Its intended users are people who edit Go in Emacs and want more than basic fontification and indentation. The mode connects familiar Emacs behavior, including `beginning-of-defun`, with Go-specific commands for formatting, documentation, imports, declaration lookup, coverage, and function signatures. This is useful when an editor should retain its existing Emacs workflow while gaining commands for a particular language.
The feature set is broad, but its architecture is not presented as a modern language server. It provides direct command integrations and targeted navigation functions. The README separately recommends `goimports` or the `organize-imports` feature of `gopls` for automatic import management, which exposes an important boundary: go-mode.el can add imports, but the project does not present that command as a complete replacement for dedicated tooling.
The command layer inside go-mode.el
Formatting is implemented through the `gofmt` command and `gofmt-before-save`. The latter is intended for an Emacs save hook, so formatting occurs when a Go buffer is saved. Changing `gofmt-command` can point the same integration at `goimports`, while setting `gofmt-args` to a list can pass options such as simplification. This design keeps formatting attached to ordinary buffer and save operations rather than requiring every formatting action to begin in another application.
Documentation access is also command-based. `godoc` and `godoc-at-point` connect the buffer to `godoc`. The mode also provides `go-play-buffer` and `go-play-region` for sending code to the Go Playground, plus `go-download-play` for opening a downloaded Playground entry. These functions cover a distinct editing workflow in which a short example can be tested without first managing a local project.
Declaration navigation relies partly on godef. `godef-describe` reports information about an expression, while `godef-jump` and `godef-jump-other-window` move to declarations. Import handling is divided between direct commands and external tools. `go-goto-imports` jumps to the import area, and `go-import-add` adds an import with tab completion, but the README recommends `goimports` or `gopls` for adding, removing, and organizing imports automatically.
Go-specific structural movement is unusually detailed. Commands such as `go-goto-arguments`, `go-goto-docstring`, `go-goto-function`, `go-goto-function-name`, `go-goto-return-values`, and `go-goto-method-receiver` target individual signature parts. The mode can skip anonymous functions when called with `C-u`. That is a focused editing facility rather than a general project-index mechanism.
Installing go-mode.el and opening the first Go buffer
The README recommends installing the mode through ELPA using the MELPA Stable repository. It does not give a standalone shell command for adding that repository to an Emacs configuration, so the verified manual route is the more complete installation example provided by the project.
For a manual installation, check out the repository into a directory, then evaluate the following configuration in Emacs. The load-path entry must match the directory where the repository was placed.
(add-to-list 'load-path "/place/where/you/put/it/")
(autoload 'go-mode "go-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.go\\'" . go-mode))Evaluate the statements with `C-x C-e`, or restart Emacs. The auto-mode rule associates files ending in `.go` with `go-mode`; the README does not document undoing either part of this configuration.
After opening a Go file, a first direct action is the `gofmt` command. This requires the corresponding Go formatting executable to be available in the environment used by Emacs. The README also documents `gofmt-before-save`, which can be used in a hook to format Go buffers before saving. It does not provide that hook example, so adding the hook would go beyond the documented setup.
Several navigation commands offer a more useful first editing pass. `C-c C-f a` calls `go-goto-arguments`, `C-c C-f d` calls `go-goto-docstring`, and `C-c C-f i` calls `go-goto-imports`. `go-goto-docstring` can create the docstring when it is absent. Running one of these commands in a real Go buffer confirms both major-mode activation and access to the signature and import navigation functions.
Configuring gofmt and optional Go tool integrations
The mode keeps formatting flexible through two documented variables. `gofmt-command` selects the formatting executable, so it can be changed to `goimports`. `gofmt-args` accepts an argument list, with `gofmt -s` given as the example. This is a useful separation between the command and its options, although the README does not show the full Lisp expression for either setting.
Documentation, declaration lookup, coverage, and Playground support rely on separate pieces of Go tooling. `godoc` is integrated by function name. godef support requires a separate installation, and the README gives this command:
go install github.com/rogpeppe/godef@latestAfter that prerequisite is available, `C-c C-d` runs `godef-describe`, `C-c C-j` runs `godef-jump`, and `C-x 4 C-c C-j` opens `godef-jump-other-window`. The README calls these godef commands integration features rather than documenting the error behavior when the executable is missing or cannot analyze a file.
Code coverage has a separate entry point named `go-coverage`, based on output calculated by `go test`. Imenu support is included for functions and variables. The project also has files named `go-guru.el` and `go-rename.el`, but the cleaned README does not explain how to configure those files, so their behavior should not be inferred from their names alone.
gopls through lsp-mode as the architectural alternative
The clearest alternative documented by the project is `gopls` used through `lsp-mode`. This differs from go-mode.el in where language intelligence comes from. go-mode.el exposes individual Emacs functions and communicates with traditional command-line tools such as gofmt, godoc, and godef. `gopls` is described as the Go team's language server implementation, with `lsp-mode` acting as its Emacs client.
The README says `gopls` is intended to replace older tools for formatting, automatic imports, code navigation, descriptions, error checking, completion, and renaming. That breadth makes it the closer choice when type-aware editor behavior is the main requirement. In contrast, go-mode.el supplies editing syntax, direct formatting integration, documentation commands, coverage display, and targeted function-signature movement.
The README provides an installation command for `gopls`:
go install golang.org/x/tools/gopls@latestIt also documents this hook for Go buffers:
(add-hook 'go-mode-hook 'lsp-deferred)According to the README, `lsp-mode` uses `gopls` automatically when it is found in `PATH`. This does not mean go-mode.el is replaced. The documented setup starts from Go major mode and adds deferred language-server behavior through `go-mode-hook`.
The maintenance boundary matters. The README contains a warning from an earlier stage of `gopls`, saying older tools would no longer be supported once it became stable. The current wording also prefers `goimports` or `gopls` for automatic import handling. Engineers should therefore distinguish go-mode.el as the editing foundation from gopls as a complementary backend for richer analysis.
Failure cases and release-channel constraints
The most immediate failure mode is a partial Go toolchain setup. `gofmt`, `goimports`, `godoc`, `gopls`, and godef are external executables, and a command works only when its required program can be invoked in the environment used by Emacs. The README documents installation for godef and gopls, but it does not give troubleshooting procedures for missing executables, failed module downloads, or incompatible Go installations.
go-mode.el is also the wrong primary choice for requirements assigned to `gopls`. The project itself describes `gopls` as the intended replacement for type and function descriptions, error checking, completion, renaming, and other language-server functions. Choosing only go-mode.el means accepting a smaller set of direct Emacs commands rather than the full language-server feature set described in the README.
Release selection creates a separate constraint. The README recommends MELPA Stable for a stable experience and says tagged releases are intended to remain stable, including APIs added in those releases. It warns that master, tracked by the normal MELPA repository, contains experimental APIs with a higher chance of bugs. Although the repository has no GitHub releases, its documentation explicitly discusses tagged releases and MELPA Stable. Repository hosting data and package stability are therefore not interchangeable signals here.
The last push was on 2026-05-29. This recent repository activity does not establish compatibility with a particular Emacs release, Go release, or external tool version, because the README does not provide such a support matrix. Users of master should expect a larger upgrade and API stability cost than users of tagged or MELPA Stable packages.
BSD-3-Clause licensing and Emacs configuration ownership
The repository uses the BSD-3-Clause license. The LICENSE file is present at the repository root, while the project metadata identifies that license. This matters for organizations reviewing how the source can be redistributed and incorporated, but this review does not provide legal advice or interpret the license obligations.
For individual Emacs users, the main upgrade work is configuration rather than application migration. Manual users need to preserve `load-path`, the `autoload` form, and the `auto-mode-alist` association. Package users must choose between the stable channel recommended by the README and the normal MELPA or master route that may contain experimental APIs. External tool upgrades are another visible part of the stack: changing `gofmt-command` to `goimports` changes what the formatting integration invokes, while adding `lsp-deferred` introduces `gopls` and `lsp-mode` into the Go editing environment.
The practical ownership boundary is clear. go-mode.el provides the major mode and its commands, but the Go distribution no longer supplies this editor integration, and several advertised capabilities depend on other executables. Anyone adopting it is adopting an Emacs configuration composed of this mode plus selected Go tools, not a self-contained Go toolchain.
Editorial conclusion
Adopt go-mode.el when working in Emacs and needing a dedicated Go editing mode with gofmt, godoc, import, and coverage commands. Do not choose it alone when your requirement is type-aware completion, diagnostics, renaming, or other language-server behavior that the README assigns to gopls. Verify first that your preferred installation channel provides a tagged or Stable version, then confirm that any external commands such as gofmt, goimports, godef, or gopls are available from your Emacs environment.
Frequently asked questions
How do I install go-mode.el in Emacs?
The README recommends ELPA through MELPA Stable. For manual installation, add the checkout directory to `load-path`, autoload `go-mode`, and associate `.go` files with it through `auto-mode-alist`.
How do I format Go code when saving in go-mode.el?
Use the documented `gofmt-before-save` hook integration. The mode also provides a `gofmt` command, while `gofmt-command` and `gofmt-args` allow selection of another formatter and additional arguments.
Should I use go-mode.el or gopls with lsp-mode?
go-mode.el supplies Emacs editing commands and integrations such as gofmt, godoc, imports, coverage, and godef. The README describes gopls through lsp-mode as the broader language-server approach for features including diagnostics, completion, navigation, and renaming, and it can be enabled from `go-mode-hook`.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dominikh-go-mode-el)Star history chart for your README
[](https://hysenlabs.com/projects/dominikh-go-mode-el)Was this useful?