Emacs Go Mode
You will notice how much I use “me” and “I” on this post. This because your emacs configuration is extremely personal. You are creating a “dream editor”, and the options that I pick might not be of your preference. Feel free to make it your own!
Back on topic. I started writing Go in late 2015. At first, I used Sublime Text, which I like a lot, but I was a little jealous of those using vim-go and I figured there would be a way to make myself at home writing Go in Emacs. This is how the adventure began.
Find a Mode!
The first thing I had to do was find a major mode for Go on emacs. It didn’t take me long to find go-mode. Installation is not hard, as it’s available as a package in the MELPA repository. A simple M-x package-install go-mode
sufficed. Configuring it was a bit harder.
Configuration
This is my .emacs
configuration for Go.
;;Load Go-specific language syntaxn;;For gocode use https://github.com/mdempsky/gocodenn;;Custom Compile Commandn(defun go-mode-setup ()n (linum-mode 1)n (go-eldoc-setup)n (setq gofmt-command "goimports")n (add-hook 'before-save-hook 'gofmt-before-save)n (local-set-key (kbd "M-.") 'godef-jump)n (setq compile-command "echo Building... && go build -v && echo Testing... && go test -v && echo Linter... && golint")n (setq compilation-read-command nil)n ;; (define-key (current-local-map) "\C-c\C-c" 'compile)n (local-set-key (kbd "M-,") 'compile)n(add-hook 'go-mode-hook 'go-mode-setup)nn;;Load auto-completen(ac-config-default)n(require 'auto-complete-config)n(require 'go-autocomplete)nn;;Go renamenn(require 'go-rename)nn;;Configure golintn(add-to-list 'load-path (concat (getenv "GOPATH") "/src/github.com/golang/lint/misc/emacs"))n(require 'golint)nn;;Smaller compilation buffern(setq compilation-window-height 14)n(defun my-compilation-hook ()n (when (not (get-buffer-window "*compilation*"))n (save-selected-windown (save-excursionn (let* ((w (split-window-vertically))n (h (window-height w)))n (select-window w)n (switch-to-buffer "*compilation*")n (shrink-window (- h compilation-window-height)))))))n(add-hook 'compilation-mode-hook 'my-compilation-hook)nn;;Other Key bindingsn(global-set-key (kbd "C-c C-c") 'comment-or-uncomment-region)nn;;Compilation autoscrolln(setq compilation-scroll-output t)
The Basics
That’s a lot! Yeah, I know, but before you freak out, I’ll give you a run down of what each block is for (although the comments should help a lot).
;;Load Go-specific language syntaxn;;For gocode use https://github.com/mdempsky/gocodenn;;Goimportsn(defun go-mode-setup ()n (go-eldoc-setup)n (add-hook 'before-save-hook 'gofmt-before-save)) n (setq gofmt-command "goimports")n (add-hook 'before-save-hook 'gofmt-before-save))n(add-hook 'go-mode-hook 'go-mode-setup)
This block enables go-mode
and makes sure it runs gofmt
before saving. gofmt
allows our code to be nice and tidy and to let go-mode
take care of importing the required packages. Nifty, huh? Makes coding nicer.
Making life even easier
Some extra elements to make our lives easier. Not necessary, but nice to have.
(defun go-mode-setup ()n ;; (setq compile-command "go build -v && go test -v && go vet && golint && errcheck")n (linum-mode 1)n (setq compile-command "echo Building... && go build -v && echo Testing... && go test -v && echo Linter... && golint")n (setq compilation-read-command nil)n ;; (define-key (current-local-map) "\C-c\C-c" 'compile)n (local-set-key (kbd "M-,") 'compile)n(add-hook 'go-mode-hook 'go-mode-setup)
This is a good one. Here I’m configuring M-,
(Escape key + comma) to run go build
, go test
, and golint
. Extremely simple way make sure our code compiles.
Autocomplete and Linting
;;Load auto-completen(ac-config-default)n(require 'auto-complete-config)n(require 'go-autocomplete)nn;;Go renamenn(require 'go-rename)nn;;Configure golintn(add-to-list 'load-path (concat (getenv "GOPATH") "/src/github.com/golang/lint/misc/emacs"))n(require 'golint)
Sets up go-autocomplete
and go-rename
. go-rename
only is used if you want to do project-level renames. Just between us, I barely use it.
The last block configures the path of the linter. Remember, Emacs is smart, but not that smart.
Beautify our editor
;;Smaller compilation buffern(setq compilation-window-height 14)n(defun my-compilation-hook ()n (when (not (get-buffer-window "*compilation*"))n (save-selected-windown (save-excursionn (let* ((w (split-window-vertically))n (h (window-height w)))n (select-window w)n (switch-to-buffer "*compilation*")n (shrink-window (- h compilation-window-height)))))))n(add-hook 'compilation-mode-hook 'my-compilation-hook)
All of this to make the compilation buffer smaller than a default buffer.
;;Other Key bindingsn(global-set-key (kbd "C-c C-c") 'comment-or-uncomment-region)
How about a simple command to comment out big blocks of code? C-c C-c
. Also, compilation-scroll-output
simply scrolls the compilation buffer all the way to the end.
What’s Left
This is my current set up. It works really well for my needs, but it might not be yours. Something I’ll work on is to integrate delve
(golang debugger) into the editor, but I suppose I’m quite old school.
I also have Magit integrated into my workflow, but that’s a topic for a different episode. To be honest, I don’t miss anything from Sublime (or Atom or MS Code), plus it already makes use of my favorite editor. A simple .emacs
file gives me all the customization that I need and I know I always have MY set up everywhere.