Posted on January 12, 2017

Ready to go (arch + emacs edition)

The arch documentation mentions two go compilers. We’re going with the official tools:

    sudo pacman -Syyu go

I tried a simple hello.go file:

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("Hello, Arch!")
    }
    

and go run hello.go produces the intended result:

    >> go run hello.go 
    Hello, Arch!

Go requires some environment variable to be setup, namely $GOPATH which usually is ~/go. After adding it to my Fish profile, I created it:

    mkdir -p ~/go/{bin,src}

and also added $GOPATH/bin to my $PATH.

To test it we use go env:

    >> go env | grep GOPATH
    GOPATH="/home/luis/go"

We’re ready to start preparing emacs! I followed suggestions from the following resources:

First up we need to get some specific go tools, which are useful even outside the context of emacs:

    go get -u golang.org/x/tools/cmd/...
    

go get should’ve downloaded to your $GOPATH/src/golang/x/tools many tools, some of which we’ll make sue of later.

Next we’re going to make emacs understand .go files and change to go-mode when we open one of these files. In your init.el or .emacs add the go-mode package.

Next we’ll be integrating some of the tools we got into emacs. To do this we need to make sure emacs know our GOPATH and for that we need to get a special package.

Add exec-path-from-shell to the packages you get from Melpa and then add the following configuration to your .emacs or init.el:

    (when window-system
      (exec-path-from-shell-initialize)
      (exec-path-from-shell-copy-env "GOPATH"))

We can test that path works ok by opneing hello.go (from before), placing the cursor over Println, M-x and chosing godoc-at-point.

Now that we have the path issue solved, let’s get some more tools. First is godef, which helps find symbol information in Go source:

    go get -u github.com/rogpeppe/godef/...
    

godef can also be tested the same way as we did with godoc.

Autocomplete is next. For this we’ll first need to go get Go specific auto-complete information:

    go get -u github.com/nsf/gocode
    

With this done, we’ll now install two Melpa packages (auto-complete and go-autocomplete) and enable auto-complete. Add the following to your emacs configuration:

    (defun auto-complete-for-go () (auto-complete-mode 1))
    (add-hook 'go-mode-hook 'auto-complete-for-go)
    
    (with-eval-after-load 'go-mode (require 'go-autocomplete))

After restarting emacs and opening a .go file you should notice already two changes:

Next is goimports which in addition to running gofmt to format the code, it also organizes the imports on the top of each Go file. goimports is a part of the tools we downloaded before, so what we need to do is enable it:

    (setq gofmt-command "goimports")
    (add-hook 'before-save-hook 'gofmt-before-save)
    

If we now go back to the hello.go file, add an import "os" line at the top and save the file, we should it disappear as goimports optimizes the import statements.

Our next step is to install Guru, a code analysis tool allows things like what calls X, find the definition of X, what are the aliases for X, among others. This step requires a very manual step, unfortunately: we need to download a .el file from Guru Project’s github and add it to our emacs initialization directory.

First we’ll get the guru .el file.

    mkdir -p ~/.emacs.d/lisp
    cd ~/.emacs.d/lisp
    wget https://raw.githubusercontent.com/dominikh/go-mode.el/master/go-guru.el
    

Now we’ll have to tell emacs to use ~/.emacs.d/lisp as another load path and enable go-guru. We add go-guru to the packages we get from Melpa and add the following to your emacs initialization:

    (add-to-list 'load-path "~/.emacs.d/lisp/")
    (require 'go-guru)
    (go-guru-hl-identifier-mode)

After restarting Emacs, we should now have Guru available. We can test it by placing the cursor in Println and hitting C-c C-o r, which is going to give us the referrers of the Println function.

That’s the beggining for me.

I found a lot more packages (go-direx, go-add-tags, go-eldoc, go-stacktracer, godoctor, flycheck + gometalinter) but I think I don’t have enough experience with Go to really make use of them.

At the same time, I don’t think my understanding of Emacs is also still in the right spot.

I have been using emacs for almost two years now but I am still only now understanding the basics of emacs initialization. I think a post on emacs initialization is more important now than going deeper on my Go configuration.