(This information was current as of 1/11/2016. As of 2022, it's rotted pretty badly, so I suggest looking elsewhere -Ben)

In case you're interested, here's what I'm using in emacs now. I think these instructions will be at least somewhat repeatable.

1. First, use an up-to-date version of emacs (I'm on the latest version, 24.5.1); I have no idea how well this will work on older versions. I install it with macports (port install emacs-app); you can also get it from homebrew (brew install emacs --cocoa). I used to use the builds from emacsformacosx.com but they seem to have memory leaks that aren't present in the macports/homebrew builds.


2. Second, set up the emacs package manager if you haven't already. Put this in .emacs:

(require 'package)
(add-to-list 'package-archives
  '("melpa" . "http://melpa.milkbox.net/packages/") t)
(add-to-list 'package-archives
    '("marmalade" .
      "http://marmalade-repo.org/packages/"))
(package-initialize)

3. Third, install the following packages with M-x package-install $PKG: go-projectile, flycheck, gotest, company, company-go. (the emacs package manager is weird; there doesn't seem to be a non-clunky way to just declare packages as dependencies of your .emacs).


4. Fourth, add this to .emacs, adjusting as necessary for your environment:

; pkg go installation
(setq exec-path (append '("/usr/local/go/bin") exec-path))
(setenv "PATH" (concat "/usr/local/go/bin:" (getenv "PATH")))

; As-you-type error highlighting
(add-hook 'after-init-hook #'global-flycheck-mode)

(defun my-go-mode-hook ()
      (setq tab-width 2 indent-tabs-mode 1)
      ; eldoc shows the signature of the function at point in the status bar.
      (go-eldoc-setup)
      (local-set-key (kbd "M-.") #'godef-jump)
      (add-hook 'before-save-hook 'gofmt-before-save)

      ; extra keybindings from https://github.com/bbatsov/prelude/blob/master/modules/prelude-go.el
      (let ((map go-mode-map))
        (define-key map (kbd "C-c a") 'go-test-current-project) ;; current package, really
        (define-key map (kbd "C-c m") 'go-test-current-file)
        (define-key map (kbd "C-c .") 'go-test-current-test)
        (define-key map (kbd "C-c b") 'go-run)))
(add-hook 'go-mode-hook 'my-go-mode-hook)

; Use projectile-test-project in place of 'compile'; assign whatever key you want.
(global-set-key [f9] 'projectile-test-project)

; "projectile" recognizes git repos (etc) as "projects" and changes settings
; as you switch between them. 
(projectile-global-mode 1)
(require 'go-projectile)
(go-projectile-tools-add-path)
(setq gofmt-command (concat go-projectile-tools-path "/bin/goimports"))

; "company" is auto-completion
(require 'company)
(require 'go-mode)
(require 'company-go)
(add-hook 'go-mode-hook (lambda ()
                          (company-mode)
                          (set (make-local-variable 'company-backends) '(company-go))))

; gotest defines a better set of error regexps for go tests, but it only
; enables them when using its own functions. Add them globally for use in
(require 'compile)
(require 'gotest)
(dolist (elt go-test-compilation-error-regexp-alist-alist)
  (add-to-list 'compilation-error-regexp-alist-alist elt))
(defun prepend-go-compilation-regexps ()
  (dolist (elt (reverse go-test-compilation-error-regexp-alist))
    (add-to-list 'compilation-error-regexp-alist elt t)))
(add-hook 'go-mode-hook 'prepend-go-compilation-regexps)

; end .emacs additions

5. Fifth, run M-x go-projectile-install-tools (one time only, although I think it would be harmless to put this in .emacs if you don't mind the extra startup time). From time to time you may need to run M-x go-projectile-update-tools.

I'm still learning all the features of this setup, but the key ones to me are: