Setting Up Emacs for Go Development
I’ve recently started learning Go, and, as with any language, I want to configure Emacs as much as possible for Go development. After scouring the Internet, this is what I’ve come up with.
Prerequisites
You’ll need Emacs and Go installed. I’m using OS X, so I use Emacs from http://emacsformacosx.com/ and this Go package.
Once you’ve installed everything, you’ll need to set a few environment variables:
export GOROOT=/usr/local/go export GOPATH=$HOME/Documents/projects/go export PATH=$PATH:$GOROOT/bin
You can set $GOPATH
to a different directory if you like.
go-mode
The first thing you’ll need for Go development in Emacs is go-mode
. You can install this easily in Emacs 24 and up with M-x package-install go-mode
.
Installing go-mode
will also let you pull up documention on the standard library or third-party packages with M-x godoc
. To make godoc
work correctly, you’ll need to make sure Emacs has the correct values of $PATH
and $GOPATH
. This shouldn’t be an issue unless you’re using GUI Emacs on OS X. If you are, I’d recommend using my env-var-import
package to import their values from the shell. That package will also set exec-path
correctly from your $PATH
, which will be important in later steps.
go-eldoc
If you’ve done any Elisp development, you’re probably familiar with eldoc. If not, eldoc shows you the argument list of the function at your point in the minibuffer. go-eldoc
is a package that does this for Go. You can install it with M-x package-install go-eldoc
. Once you’ve done that, you’ll need to enable it:
(defun go-mode-setup () (go-eldoc-setup)) (add-hook 'go-mode-hook 'go-mode-setup)
gofmt
One of the things I really like about go is the automatic enforcement of a consistent coding style via gofmt
. You could manually run this on your code, but go-mode
lets you configure Emacs to run it automatically when you save a buffer:
(defun go-mode-setup () (go-eldoc-setup) (add-hook 'before-save-hook 'gofmt-before-save)) (add-hook 'go-mode-hook 'go-mode-setup)
goimports
There is also a tool called goimports
that not only formats your code like gofmt
but also automatically updates all your imports. I’d recommend using this instead of gofmt
.
You’ll need Mercurial installed first in order to install it. Then you can run go get code.google.com/p/go.tools/cmd/goimports
. Now you can tell Emacs to use goimports
instead of gofmt
:
(defun go-mode-setup () (go-eldoc-setup) (setq gofmt-command "goimports") (add-hook 'before-save-hook 'gofmt-before-save)) (add-hook 'go-mode-hook 'go-mode-setup)
godef
Installing go-mode
will also give you godef
, which will let you jump to the definition of a function like in an IDE. You can jump with M-x godef-jump
and then return to the original point with M-*
. I bound godef-jump
to M-.
for ease of use:
(defun go-mode-setup () (go-eldoc-setup) (setq gofmt-command "goimports") (add-hook 'before-save-hook 'gofmt-before-save) (local-set-key (kbd "M-.") 'godef-jump)) (add-hook 'go-mode-hook 'go-mode-setup)
Custom compile command
You can use M-x compile
to compile and test your code from Emacs. You’ll just need to set the command that compile
runs:
(defun go-mode-setup () (setq compile-command "go build -v && go test -v && go vet") (define-key (current-local-map) "\C-c\C-c" 'compile) (go-eldoc-setup) (setq gofmt-command "goimports") (add-hook 'before-save-hook 'gofmt-before-save) (local-set-key (kbd "M-.") 'godef-jump)) (add-hook 'go-mode-hook 'go-mode-setup)
I also bound C-c C-c
to run compile
.
Autocomplete
The last step is to set up autocompletion for Go. I use the auto-complete
package for other languages, so it’s natural to use it here too. For Go-aware autocomplete, you’ll need to install the gocode
tool first with go get -u -v github.com/nsf/gocode
. Then you can install auto-complete
with M-x package-install auto-complete
and go-autocomplete
with M-x package-install go-autocomplete
. Once you’ve installed everything add the following to your Emacs configuration:
(require 'auto-complete-config) (require 'go-autocomplete)
Now you’re ready to start writing some Go in Emacs!