Send me an email!
Writing Go in Emacs
Using the right tools plays a big role in getting your job done efficiently. In the case of programming Go, most of your time will be spent in an editor. It is therefore key that your editor doesn’t get in your way and, optimally, assists you wherever it can.
In this article, I will talk about go-mode for Emacs, its history and features, as well as useful extensions to it.
Even though this article is targeted at Emacs users, parts of it, mainly the feature list, might be of interest to users of other editors as well, to see what’s possible and to adopt some of the ideas. You will want to skip the History and Obtaining it sections though.
History of go-mode
Go has been including a mode for Emacs for a long time now. Until
recently, however, it was rather fragile. It regularly messed up
indentation or syntax highlighting, for quite some time it could
completely lock up your editor and it didn’t feel really integrated in
Emacs, lacking support for functions like beginning-of-defun
. It
also didn’t include a lot of extra features.
All in all, it was better than having to use nano, but not by much.
All that changed around February this year, when I rewrote the mode from scratch. I took special care to build it on top of a solid foundation, making use of Emacs’s parsing facilities, as opposed to the previous version of the mode, which implemented its own parser. Apart from generally bug-free behavior, this also allowed building a lot of functions on top of it.
Obtaining it
There are two ways of obtaining go-mode and both are very similar. The first way is using the one that comes with the Go distribution itself, the second way is to get it from GitHub, where I push all new changes before they find their way into the Go repository.
When using the one that comes bundled with Go, be sure to use the one that comes with tip, the development version of Go. The current release, 1.0.3, includes the old, outdated version of go-mode.
Installation
If using go-mode from Go tip, put both go-mode.el
and go-mode-load.el
into a directory of your choice, add it to Emacs’s load paths via
(add-to-list 'load-path "/place/where/you/put/it")
and require it via
(require 'go-mode-load)
This will install autoload entries and associate *.go
files with
go-mode.
If using go-mode from the git repository, the procedure is similar,
but requires an additional step to generate the go-mode-load.el
file. From within Emacs, run M-x update-file-autoloads
, point it at
the go-mode.el
file and tell it to generate a go-mode-load.el
file.
From that point on the procedure is the same as before.
Features
For Emacs, a programming mode is often about more than just indentation and syntax highlighting. Integration with the tools of the language is often key, easy navigation of code, even crossing package boundaries, is appreciated and some people even rely on on-the-fly syntax checking.
go-mode, either directly or by using the work of others, offers all of this and more.
We’ll discover how to read documentation, format and navigate code, how to use Go’s own pastebin, how to get syntax checking, autocompletion and snippets.
Reading documentation
Using the godoc
function, you can invoke the identically named Go
tool from within Emacs and read package documentation in a view-mode
buffer. Additional feature: You can tab complete import paths.
Formatting code
Maybe one of the most important tools of Go is gofmt, which automatically formats your code to the one true coding style, used by every Go developer.
In Emacs, there are two ways to use gofmt. One way is to invoke
gofmt manually with the identically named function gofmt
, which
will patch the current buffer according to gofmt. The other way is to
use a before-save-hook to run gofmt
every time you save a Go buffer.
Enabling that hook is as easy as doing
(add-hook 'before-save-hook 'gofmt-before-save)
If you have used this hook before and complained about your cursor jumping around, don’t worry: This has been fixed in the new go-mode. At the very most, your cursor will be placed on the beginning of the current line, if it had to be reformatted.
Managing imports
On a first glance, managing imports in Go doesn’t seem like much of a deal. You either add import statements at the top of your file or you remove them. But when rapidly developing a new application, this can cause a lot of jumping around. Did you just realize that you forgot to import the fmt package? Previously, this meant going to the beginning of the buffer, advancing to the block of import statements (if it existed yet), going to its end and adding your new import. And when you realized you didn’t need it after all, you had to repeat the same procedure to remove it again.
The new go-mode has three functions for working with imports:
go-import-add
, go-remove-unused-imports
and go-goto-imports
.
go-import-add
go-import-add
, bound to C-c C-a
by default, will prompt you for an
import path (again supporting tab completion) and insert it in the
import block, creating it if necessary. If an import already existed
but was commented, it will be uncommented.
If prefixed with C-u
, it will ask you for an alias, too. An annoying
procedure of moving around and mental context switching has just been
reduced to a keystroke.
go-remove-unused-imports
Instead of offering a function for removing a single import, go-mode
will detect all unused imports and delete them (or comment them) once
you run go-remove-unused-imports
. It is not bound to a key by
default, but you can bind it yourself if you want to. Personally I
have bound it to C-c C-r
:
(add-hook 'go-mode-hook (lambda ()
(local-set-key (kbd "C-c C-r") 'go-remove-unused-imports)))
go-goto-imports
If you decide you want to look at your imports or edit them manually, go-goto-imports will take you to them automatically, placing your cursor after the last import. It isn’t bound to a key, either, mainly because I couldn’t come up with a good default that didn’t violate Emacs guidelines. But you can bind it manually, just like before:
(add-hook 'go-mode-hook (lambda ()
(local-set-key (kbd "C-c i") 'go-goto-imports)))
Navigating code
Also important for efficient programming is quick navigation of code.
go-goto-imports
was only the tip of the iceberg.
go-mode supports beginning-of-defun
(C-M-a
) and end-of-defun
(C-M-e
), two core Emacs functions for navigating between functions.
Additionally, functions such as narrow-to-defun
and mark-defun
rely on these two functions.
If that isn’t enough, you can also use Imenu to jump to specific function or type declarations.
Even if you long for a feature that’s usually only provided by IDEs, or by making use of etags, namely jumping to the declaration of a symbol under your cursor, go-mode got you covered.
go-mode integrates with godef, an amazing little tool written by Roger Peppe. godef is able to parse your code, and the code of other packages, and the code of the Go standard library, and can tell you what exactly the symbol you’re looking at means and where it has been defined.
go-mode makes use of this to provide the two functions
godef-describe
and godef-jump
. godef-describe
will tell you what
you’re looking at, while godef-jump
will take you to its definition.
And yes, this works across files, packages and into the standard
library, without needing any tags. And it has almost no measurable
delay.
godef-describe
is bound to C-c C-d
and godef-jump
is bound to
C-c C-j
. If you want to, you can bind godef-jump
to M-.
, which
is the default key for find-tag
, something you might already be
using for other programming languages:
(add-hook 'go-mode-hook (lambda ()
(local-set-key (kbd \"M-.\") 'godef-jump)))
There are two important notes:
-
Update (2013-03-19): The godef features in go-mode are now part of the Go repository. As of writing this article, the godef functions haven’t reached the Go repository yet. They are only available in the git version. This will hopefully change in the next couple of days.
-
You will obviously need to install godef, which is as easy as doing
go get code.google.com/p/rog-go/exp/cmd/godef
.
Interacting with the Playground
Go has its own pastebin, called the Playground. When asking for help with code, or sharing solutions to those who need help, it is often expected to use the Playground, especially because it can execute code.
It makes sense that go-mode integrates with the Playground. It offers
go-play-buffer
and go-play-region
to send the current buffer or
region to the Playground and store a link in your kill ring.
It can also directly download a paste from the Playground into Emacs,
by using go-download-play
.
On-the-fly syntax checking
FlyMake is Emacs’s solution to on-the-fly syntax checking. Many programming modes offer support for it (some more easily than others).
In the case of Go, Doug MacEachern wrote goflymake, which consists of a small Go binary and some elisp to integrate it with Emacs. Because Go compiles blazingly fast, using goflymake doesn’t cause any performance penalties. Personally I am letting FlyMake compile my Go buffers every time I insert a newline. More conservative settings would compile after a certain amount of idle time, or when saving the buffer.
Autocompletion
gocode, written by nsf, provides the kind of autocompletion that you might know from IDEs. It provides context-sensitive autocompletion and works across a variety of editors, including Emacs. The project’s README includes detailed installation instructions.
Note: it suggests using auto-complete-mode and mentions company-mode as an alternative. Personally I recommend trying company-mode first. auto-complete-mode isn’t as lightweight and can be harder to configure.
Snippets
Some people like them, some think they’re useless: Snippets. Short words that, upon pressing TAB, turn into longer words, sentences or code constructs. One of the more popular implementations of snippets for Emacs is YASnippet, and it is YASnippet that I wrote a small number of Go snippets for.
Finding unchecked errors with go-errcheck
Last but not least, there’s go-errcheck, offering Emacs integration for errcheck. errcheck is a tool written by Kamil Kisiel for finding and reporting unchecked errors in your Go code.
go-errcheck offers the go-errcheck
function, which will run errcheck
on the current package and report errors in a compilation buffer.
Additionally, it supports setting errcheck flags on a default and
per-package basis.
Conclusion
I hope I was able to give you a good overview of the features that you can enjoy while writing Go code in Emacs. If I forgot any cool packages, or if you have suggestions or comments, please leave me a message. Check the contact page to find ways of contacting me.