Emacs mode for the Go programming language

Related tags


This is go-mode, the Emacs mode for editing Go code.

It is a complete rewrite of the go-mode that shipped with Go 1.0.3 and before, and was part of Go 1.1 until Go 1.3. Beginning with Go 1.4, editor integration will not be part of the Go distribution anymore, making this repository the canonical place for go-mode.


In addition to normal features, such as fontification and indentation, and close integration with familiar Emacs functionality (for example syntax-based navigation like beginning-of-defun), go-mode comes with the following extra features to provide an improved experience:

  • Integration with gofmt by providing a command of the same name, and gofmt-before-save, which can be used in a hook to format Go buffers before saving them.

    • Setting the gofmt-command variable also allows using goimports.
    • Setting the gofmt-args variable with a list of arguments allows using e.g. gofmt -s.
  • Integration with godoc via the functions godoc and godoc-at-point.

  • Integration with the Playground

    • go-play-buffer and go-play-region to send code to the Playground
    • go-download-play to download a Playground entry into a new buffer
  • Managing imports

    • A function for jumping to the file's imports (go-goto-imports - C-c C-f i)
    • A function for adding imports, including tab completion (go-import-add, bound to C-c C-a)
    • A function for removing or commenting unused imports (go-remove-unused-imports)
    • It is recommended that you use goimports or the organize-imports feature of gopls to manage adding/removing/organizing imports automatically.
  • Integration with godef

    • godef-describe (C-c C-d) to describe expressions
    • godef-jump (C-c C-j) and godef-jump-other-window (C-x 4 C-c C-j) to jump to declarations
    • This requires you to install godef via go get github.com/rogpeppe/godef.
  • Basic support for imenu (functions and variables)

  • Built-in support for displaying code coverage as calculated by go test (go-coverage)

  • Several functions for jumping to and manipulating the individual parts of function signatures. These functions support anonymous functions, but are smart enough to skip them when required (e.g. when jumping to a method receiver or docstring.)

    • Jump to the argument list (go-goto-arguments - C-c C-f a)
    • Jump to the docstring, create it if it does not exist yet (go-goto-docstring - C-c C-f d).
    • Jump to the function keyword (go-goto-function - C-c C-f f)
    • Jump to the function name (go-goto-function-name - C-c C-f n)
    • Jump to the return values (go-goto-return-values - C-c C-f r)
    • Jump to the method receiver, adding a pair of parentheses if no method receiver exists (go-goto-method-receiver - C-c C-f m).

    All of these functions accept a prefix argument (C-u), causing them to skip anonymous functions.

  • GOPATH detection – the function go-guess-gopath will guess a suitable value for GOPATH, based on gb or wgo projects, Godeps and src folders for plain GOPATH workspaces. The command go-set-project uses the return value of go-guess-gopath to set the GOPATH environment variable.

    You can either call go-set-project manually, or integrate it with Projectile's project switching hooks, or any other means of switching projects you may employ.



The recommended way of installing go-mode is via ELPA, the Emacs package manager, and the MELPA Stable repository, which provides an up-to-date version of go-mode.

If you're not familiar with ELPA yet, consider reading this guide.


To install go-mode manually, check out the go-mode.el repository in a directory of your choice, add it to your load path and configure Emacs to automatically load it when opening a .go file:

(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))

Either evaluate the statements with C-x C-e, or restart Emacs.

Other extensions

There are several third party extensions that can enhance the Go experience in Emacs.

Gopls integration

Gopls is the official language server protocol (lsp) implementation provided by the Go team. It is intended to replace the existing third party tools for code formatting (gofmt), automatic imports (goimports), code navigation (godef/guru), type and function descriptions (godoc/godef), error checking, auto completion (gocode), variable and type renaming (rename), and more. Once gopls is stable the older tools will no longer be supported.

Gopls is a supported backend for lsp-mode. It will be used automatically by lsp-mode if gopls is found in your PATH. You can install gopls via: go get golang.org/x/tools/[email protected]. To enable lsp-mode for go buffers:

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

Syntax/error checking

There are two ways of using flymake with Go:

  1. goflymake, which internally uses go build to capture all errors that a regular compilation would also produce
  2. flymake-go for a more lightweight solution that only uses gofmt and as such is only able to catch syntax errors. Unlike goflymake, however, it does not require an additional executable.

Additionally, there is flycheck, a modern replacement for flymake, which comes with built-in support for Go. In addition to using go build or gofmt, it also has support for go vet, golint and errcheck.

Auto completion

For auto completion, take a look at gocode.


https://github.com/syohex/emacs-go-eldoc provides eldoc functionality for go-mode.


I maintain a set of YASnippet snippets for go-mode at https://github.com/dominikh/yasnippet-go

Integration with errcheck

https://github.com/dominikh/go-errcheck.el provides integration with errcheck.


go-mode.el has regular, tagged releases and is part of the MELPA Stable repository. These tagged releases are intended to provide a stable experience. APIs added in tagged releases will usually not be removed or changed in future releases.

Changes made on the master branch, which is tracked by the normal MELPA repository, however, are under active development. New APIs are experimental and may be changed or removed before the next release. Furthermore, there is a higher chance for bugs.

If you want a stable experience, use MELPA Stable. If you want cutting edge features, or "beta-test" future releases, use MELPA or the master branch.

  • Add goto functions for working with function signatures

    Add goto functions for working with function signatures

    Add several functions:

    • go-goto-arguments
    • go-goto-docstring
    • go-goto-function
    • go-goto-function-name
    • go-goto-return-value
    • go-goto-type-signature

    They are all about going to different parts of function signatures, with their names being self descriptive. They all operate on the current function, the definition of which is "the closest func statement above point". If no func is found above point, the functions will jump to the first func in the file. Lastly, if the point is in the docstring of a function, the goto functions will operate on that function and not the function above.go-goto-type-signature

    Additionally, some of the functions will create their targets if they are missing:

    • go-goto-docstring will create a docstring if it does not exist as well as update the docstring name for a function that has been renamed.
    • go-goto-return-value will add space for adding return values.
    • go-goto-type-signature will add spaces and a pair of parenthesis for adding a signature.

    It should also be noted that the functions have been tested with anonymous functions as well.

    Add keymap at C-c g for goto functions. Add mapping for the already existing go-goto-imports at C-c g i. Add helper function go--get-function-name, which grabs the string of the function above point.

    Update README to reflect the addition of these functions.

    I have been using these functions for about a month now. They feel stable enough that they can be shared with the upstream go-mode.

    It should be noted and is probably apparent that this is my first real contribution to a project written in elisp (or any lisp at all, actually :dancer:). As such, I am probably missing out on conventions, useful functions and other such things. I'd be very happy to change the code so that it fits well into the project! Comments on coding style and such things are extremely welcome!


    • [x] go-goto-docstring should not update the docstring
    • [x] Keybinds should not be on the user bindable keyspace.
    • [x] Move all define-key to one single place.
    • [x] go-goto-arguments has a copy-pasted docstring
    • [x] ~~Handle going to docstrings with prepending words (A foo etc)~~
    • [x] Fix corner cases for go-goto-function
    • [x] Don't skip past the pointer in go-goto-return-value
    • [x] Use forward-list instead of searching for ).
    • [x] go-goto-type-signature has the wrong name.
    • [x] Docstring and comments for go--in-function-p are wrong
    • [x] go-goto-docstring has a bug with empty comments above a function
    • [x] Add prefix arguments and handling of special cases for anonymous functions
    • [x] Fix bug in go-goto-docstring in the empty comments case
    • [x] Remove get- from go--get-function-name
    • [x] Handle prefix arguments as booleans
    • [x] Fix logical errors in go--in-function
    • [x] Handle prefixed non-interactive calls to go-goto-docstring and go-goto-method-receiver.
    • [x] Make go--function-name return nil for anonymous functions.
    opened by thiderman 50
  • gofmt breaks kill-ring

    gofmt breaks kill-ring

    I have no idea why this is the case, but I've found that kill-line and kill-region work as expected when I first start emacs. After running gofmt in a buffer, however, text that is killed is no longer added to the kill-ring.

    Emacs version: 24.3.1

    opened by colegleason 19
  • Add option to not show gofmt errors in new buffer

    Add option to not show gofmt errors in new buffer

    I already use flycheck+helm to show and navigate errors, so popping up a new buffer after running gofmt-command is unnecessary and disruptive. This makes the behavior optional.

    opened by steffiefee 17
  • Fontify variable declarations

    Fontify variable declarations

    Variable names should be highlighted with font-lock-variable-name-face where the variable is declared. For example, u, v, x, y, and z should be highlighted in the following:

    var x, y = 1, 2
    x, y := 1, 2
    for x, y := range aSlice {
    func f(x, y int) (u, v bool)
    func(x int, y char) (z bool)
    func (x T) MyMethod(y int) (z int)

    Highlighting variable declarations is performed in Emacs Lisp mode (for "defvar") and c-mode (for function parameters and variable declarations). I miss it in go-mode.

    BTW, Thank you very much for the improved go-mode!

    enhancement cosmetics 
    opened by glenn-brown 17
  • Add comma to go-dangling-operators-regexp ?

    Add comma to go-dangling-operators-regexp ?


    a,b :=


    a,b :=
    bug indentation 
    opened by Bad-ptr 16
  • Support outline-minor-mode

    Support outline-minor-mode

    Is it possible to add support for outline-minor-mode? outline style code folding makes it much easier to work with large source code files. This is esp. useful for go-lang as one can keep the whole package source in a single file which makes code searching and navigation much easier.

    python.el https://github.com/fgallina/python.el works with outline-minor-mode for Python and can be used as a reference. It defines two regexps: outline-regexp and outline-heading-end-regexp, and one function outline-level.

    Reference for outline minor mode can be found here: http://emacswiki.org/emacs/OutlineMinorMode

    opened by fspeech 14
  • go-mode does not correctly highlight Go types

    go-mode does not correctly highlight Go types

    Currently, Go types such as int32, float64 etc. are not recognized as part of Go's syntax:

    package main

    import "fmt"

    func main() { var testvar int32 }

    In the above piece of code, 'int32' is not highlighted, even trough it is a valid Go type. gomode

    enhancement cosmetics 
    opened by MatejLach 13
  • go-remove-unused-imports doesn't remove any imports

    go-remove-unused-imports doesn't remove any imports

    If I edit an existing Go file, and add package to the import list that isn't referenced anywhere, then invoke go-remove-unused-imports, no imports are removed, even though the compiling the file results in an unused import error.

    Using the code with go-flymake, gocode, and auto-complete enabled. I haven't tried turning them off yet.

    opened by markcol 13
  • Extract gofmt foundation as a separate package

    Extract gofmt foundation as a separate package

    Could you extract the gofmt foundation as a seprate package?

    There are a lot of formatting elisp packages based on gofmt of go-mode.el. I think it is reasonable to extract gofmt foundation as a separate package and make it usable for them as a library.

    Using this package, the following code defines gofmt function, gofmt-before-save function and gofmt-show-errors customizable variable.

    (define-langfmt gofmt
      "Format the current buffer according to the gofmt tool."
      :group 'go
      :modes '(go-mode)
      :format-command gofmt-command
      :format-args '("--w")
      :format-handler (lambda (exit-status)
                        (unless (zerop exit-status)
                          (message "Could not apply gofmt")))
      :diff-handler (lambda (_ no-diff-p)
                      (message (if no-diff-p
                                   "Buffer is already gofmted"
                                 "Applied gofmt")))
      :error-filter (lambda (filename tmpfile)
                      (while (search-forward-regexp
                              (concat "^\\(" (regexp-quote tmpfile) "\\):") nil t)
                        (replace-match (file-name-nondirectory filename)
                                       t t nil 1))))

    This is a part of my attempt for JSCS (JavaScript Code Style) fixer in jscs.el (papaeye/emacs-jscs#1).

    Please feel free to rewrite the code and/or rename the package as you like!

    opened by papaeye 12
  • Problem with multiple workspaces (Godep)

    Problem with multiple workspaces (Godep)

    I am using spacemacs (develop branch). The go integration that comes with it mostly delegates to go-mode.el.

    I am also using godep, so my $GOPATH looks like this:

    Now, if I try to gorename from emacs, I get

    It can not find negroni package because is installed in godeps workspace.

    But if I do the same from the command line, it works:

    In emacs, evaluating (getenv "GOPATH") produces the correct path:

    So what it is wrong? Is it me? Or is it a bug? I tried to look at your code, but I am a complete emacs/lisp n00b, so didn't get far :)


    opened by artemave 12
  • Mentioning NonGNU ELPA

    Mentioning NonGNU ELPA


    this is just to let you know that go-mode has been added to the NonGNU ELPA repository. It will be enabled by default from Emacs 28 and onwards making go-mode easier to install.

    Form a packaging perspective, the main differences are that NonGNU checks for commits that bump the version tag when identifying stable releases (instead of tagged commits like MELPA) and that by default, stable versions are distributed.

    In case you are interested, feel free to mention that go-mode can be installed via NonGNU ELPA: https://elpa.nongnu.org/nongnu/go-mode.html

    opened by phikal 0
  • New stable version?

    New stable version?

    I notice that there hasn't been a stable release since v1.5.0 in March of 2017. Will there ever be another one? Or is it just that master is stable enough for everyday use?


    opened by akalin 0
  • Make fill-paragraph work in multi-line back-quoted strings

    Make fill-paragraph work in multi-line back-quoted strings

    It would be nice if fill-paragraph (ALT-Q on standard bindings) worked in multi-line back-quoted strings .

    I use multi-line quotes like this to provide help

    var help = `
    Lots of nice long help text.
    Spread out over lots of lines

    And in editing that help for a terminal fill-paragraph would be super useful!

    My current workaround is to drop into text-mode to do the fill-paragraph then return to go-mode.

    I'll note that python-mode allows fill-paragraph in its equivalent triple quoted strings.

    PS Thanks for writing go-mode - it is a great timesaver :-)

    opened by ncw 4
  • Bad font locking for triple func call

    Bad font locking for triple func call


    var f func(int) func(int) func(int)

    "456" is fontified as a function.

    opened by muirdm 0
  • [Feature Request] Syntax highlighting in the result of `godoc-at-point`

    [Feature Request] Syntax highlighting in the result of `godoc-at-point`

    It would be nice to have syntax highlighting in the result of godoc-at-point.

    opened by updogliu 0
  • Does not align closing parenthesis

    Does not align closing parenthesis

    Not sure if it is this plugin responsibility or some generic emacs configuration.

    if myvar {

    Expect the closing parenthesis to be on the same indentation level as if. It works find for other languages I work with, e.g. C++, javascript.

    opened by ChoppinBlockParty 6
  • fix: go-guru-definition jump to wrong position by wrong coding-system.

    fix: go-guru-definition jump to wrong position by wrong coding-system.

    When default coding-system is "utf-8-unix" and open a file with "utf-8-dos" coding-system, go-guru-definition will jump to wrong position.

    This is because windows's EOL is "\r\n", is different with linux's "\n", so we must keep the EOL unchanged when process internally.

    opened by tangxinfa 1
  • Fix ‘go-test’ compilation message pattern.

    Fix ‘go-test’ compilation message pattern.

    Fixes #361 Fixes #362

    Restrict the prefix and filename pattern (Bug #361), and also allow for a test name prefix (Bug #362).

    Add regression tests for these bugs.

    opened by phst 0
  • go-test compilation error pattern doesn't match Go 1.14 output

    go-test compilation error pattern doesn't match Go 1.14 output

    The output of go test -v has changed somewhat in Go 1.14. For example, with this /tmp/f/foo_test.go:

    package foo_test
    import "testing"
    func Test(t *testing.T) {

    the Go 1.13 output is

    === RUN   Test
    --- FAIL: Test (0.00s)
        foo_test.go:6: 1
    exit status 1
    FAIL	_/tmp/f	0.010s

    but the Go 1.14 output is

    === RUN   Test
        Test: foo_test.go:6: 1
    --- FAIL: Test (0.00s)
    exit status 1
    FAIL	_/tmp/f	0.011s

    Note that the error message now has the prefix Test: (i.e. test name, colon, space). This is probably related to the change described at https://golang.org/doc/go1.14#go-test. However, the go-test pattern treats the entire Test: foo_test.go part as filename.

    go-test should be adapted accordingly.

    opened by phst 0
  • Regular expression for go-test compilation pattern is too broad

    Regular expression for go-test compilation pattern is too broad

    The regular expression to find Go test errors is currently (https://github.com/dominikh/go-mode.el/blob/734d5232455ffde088021ea5908849ac570e890f/go-mode.el#L1845) "^\\s-+\\([^()\t\n]+\\):\\([0-9]+\\):? .*$". The problem is that this regex is very broad and matches too much:

    1. The \s-+ also matches newlines (at least when using the standard syntax table).
    2. The [^()\t\n]+ group matches a ton of things: spaces, exotic characters, NUL bytes, ...

    Combined, these two mean that e.g. a GNU-style file:line:column: message line that follows a newline is matched incorrectly:

    (with-syntax-table (standard-syntax-table)
      (let ((regex "^\\s-+\\([^()\t\n]+\\):\\([0-9]+\\):? .*$")
            (line "\nfile.go:1:2: word word"))
         (string-match regex line)
         (match-string 1 line))))
    ⇒ (0 "file.go:1")

    Here, this incorrectly treats file.go:1 as filename and 2 as line number. This causes issues because such lines are very common in practice, and the leading newline alone is enough to trigger go-test matching.

    I recommend restricting the go-test pattern:

    1. Replace the \s-+ by a more precise match, e.g. four spaces.
    2. Replace the filename group by something that is likely to be an actual filename (e.g. no spaces or colons).
    opened by phst 0
Dominik Honnef
Long-time Go user, contributor, and author of many Go related tools, including staticcheck.
Dominik Honnef
gide is an IDE framework in pure Go, using the GoGi gui. It extensively adopts emacs keybindings.

Gide Gide is a flexible IDE (integrated development environment) framework in pure Go, using the GoGi GUI (for which it serves as a continuous testing

GoKi 105 Aug 26, 2021
A very religious text editor

--== Godit - a very religious text editor ==-- Screenshots: * https://nosmileface.dev/images/godit-linux1.png * https://nosmileface.dev/images/god

null 519 Sep 8, 2021
Go extension for VS Code

Go for Visual Studio Code The VS Code Go extension provides rich language support for the Go programming language. Quick Start Welcome! ???? Whether y

Go 2k Sep 12, 2021
A Go language server.

A Go Language Server based on the Go Extension for Visual Studio Code Wraps the VSCode Go extension from Microsoft into a language server, such that i

theia-ide 32 Aug 17, 2021
Theia Go Extension

Theia Go Extension An extension for the Theia-IDE to support the Go language, using the Go language server. Getting started Install nvm. curl -o- http

theia-ide 15 Jan 17, 2021
Binary editor written in Go

bed Binary editor written in Go Screenshot Why? Why not? Programming is so fun! I learned so much while creating this editor; handling of file pointer

itchyny 1.1k Sep 7, 2021
A graphical text editor

A A is a text editor inspired by the Sam and Acme text editors for the Plan 9 operating system. binary Latest Binaries https://github.com/as/a/release

null 286 Sep 8, 2021
A modern and intuitive terminal-based text editor

micro is a terminal-based text editor that aims to be easy to use and intuitive, while also taking advantage of the capabilities of modern terminals.

Zachary Yedidia 17.6k Sep 7, 2021
A terminal based game that teaches you how to use Vim.

VimMan Learn how to use Vim in its natural environment, the Terminal! About VimMan is terminal program that's a semi editor and a semi game. The purpo

Ozan Kaşıkçı 137 Aug 14, 2021
Eclipse IDE for the Go programming language:

Project website: http://goclipse.github.io/ As of 2017, Goclipse is no longer actively maintained, see this blog post for more information. If you are

null 841 Sep 2, 2021
chkb turns a regular keyboard into a fully programmable keyboard. It is a cheap programmable keyboard

chkb chkb turns a regular keyboard intro a fully programmable keyboard. So you basically get a cheap programmable keyboard. It has been inspired by QM

Victor 30 Sep 9, 2021
BBEdit package for Go development

BBEdit package for Go development Features Full language syntax highlighting Support for code folding func Language defaults Full set of clippings Go

Andrew Carter 33 Jul 27, 2021
Web-based IDE for the Go language

Welcome to godev! The aim of this project is to develop a premier Go language IDE hosted in a web interface. This was inspired by the way that the god

Chris McGee 349 Aug 3, 2021
Vim plugin for https://github.com/hexdigest/gounit

gounit-vim Vim plugin for gounit tool that allows you to generate Go tests easily. Demo Installation gounit-vim requires gounit to be available in you

Max Chechel 22 Jun 30, 2021
Conception was an experimental project, looking for ways to make software development more efficient.

Conception Note: All future development is done in the Go version. Conception is an experimental research project, meant to become a modern IDE/Langua

null 530 Aug 18, 2021
Go development plugin for Vim

vim-go Features This plugin adds Go language support for Vim, with the following main features: Compile your package with :GoBuild, install it with :G

Fatih Arslan 13.8k Sep 13, 2021