Getting started with Go (and Emacs)

Dumping some notes I took while I was setting up my environment and reading the bare minimum to get started with Go programming.

Go setup

  • I’m on Mac and I had some older version of Go already installed, so I had to brew uninstall go.
  • Go 1.22 had recently come out, and it wasn’t yet available in brew, so I downloaded it from the Go website.
  • I had to add this to my ~/.zshrc for my shell to pick up the installation (source):

    export GOPATH=$HOME/go
    export GOROOT=/usr/local/go
    export GOBIN=$GOPATH/bin
    export PATH=$PATH:$GOPATH
    export PATH=$PATH:$GOROOT/bin
    export PATH=$PATH:$GOPATH/bin

Emacs setup

In the last couple of years the Emacs LSP integration has got good enough that, other things being equal, I prefer it when I’m setting up a new language since it provides a similar out-of-the-box experience to what I’m used to, without much extra configuration.

  • A quick search for recent Go+Emacs setup suggestions didn’t yield a definite choice, but I did see a few people using go-mode together with LSP, so I went with that.
  • go install to install gopls, the Go server the lsp-mode expects.
  • go install for the staticcheck linter.

This is what my Emacs config looks like:

(require 'lsp-mode)
(require 'go-mode)

(add-hook 'go-mode-hook 'lsp-deferred)
(add-hook 'go-mode-hook 'subword-mode)
(add-hook 'before-save-hook 'gofmt-before-save)

(add-hook 'go-mode-hook (lambda ()
                          (setq tab-width 4)
                          (flycheck-add-next-checker 'lsp 'go-vet)
                          (flycheck-add-next-checker 'lsp 'go-staticcheck)))

The only issues I’ve found so far:

  • lsp-describe-thing-at-point does give me function documentation, but only the first sentence, not the entire paragraph. I end up using xref-find-definitions and read directly from the doc comment in the code.
  • flycheck’s next-error doesn’t seem to work consistently in my Go setup as it does in other languages.

GitHub setup

  • I started with a default GitHub Actions workflow to run unit tests, which I extended to also run linters.
  • I eventually wrote another workflow to draft a release and compile binaries for different platforms when I push a git tag.

Go documentation

I had read The Little Go Book a few years ago, and while I didn’t do anything with what I read there and thus forgot most of it, I did remember that there wasn’t anything surprising or complicated enough to require dedicated training before attempting to use the language.

This time I took a look a Go’s learn and docs pages, but they didn’t point me in a single obvious direction. There was the Effective Go book, which sounded like the kind of resource I tend to favor: text form, not very long, by the language authors. But it started with a note saying it was written in 2009 and hadn’t been updated since, which made it unappealing for my short-term goals. I may revisit it eventually, though, since I understand it was the canonical learning resource for many years and a good showcase of Go’s idiosyncrasy.

I turned to the official tutorials, but after the first hello world they got into the weeds of modules and workspaces, without enough context for them to be useful starter resources. (In fact, they side-tracked me to read more about modules and project layout, to try to understand how Go compares to other languages on those fronts).

What ended up working for me was just trying to implement my project’s basic features, starting from the hello world program, looking up what I didn’t know in Go by Example (which had at least preliminary answers for most of my questions), then jumping to the package documentation for details. I’m sure I missed out on language features and idioms, but it was amazing to start making steady progress just a day after first installing Go.

I took note of some resources I could go back to, to dive deeper into the language once project development winds down:

I will elaborate on my first impressions of the language in a later post.