with the flow

@ Golang BCN

by @gonzaloserrano

clip by Queens of the Stone Age :metal:

Thanks! :moneybag: :beer:

About me


  • programming
  • coding time
  • repetition
  • automation
  • productivity
  • fun

I'm not a great programmer; I'm just a good programmer with great habits. ― Kent Beck

mandatory editor war poll :clipboard:

    Raise :hand: !
  • vi (vim, gvim, neovim)
  • emacs
  • intellij
  • vscode
  • atom
  • eclipse
  • sublime
  • others?

mandatory quotes :speech_balloon:

Software engineering requires tools.
Go [...] was designed to make tools easy to write. Tools to manipulate Go programs are so easy to write that many such tools have been created.
They also make it easy to write more modest programs such as IDE plugins, for instance. All these items build on each other, making the Go environment more productive by automating many tasks.
Vim is like The Wire - you need to stick with it
someone on the internet

About vim

Strengths :muscle:

  • modal
  • extensible
  • found everywhere

More info

Shameless self-promotion :blush:

extensibility :wrench::nut_and_bolt:

  • vim-go
  • Fatih Arslan, Digital Ocean
  • integrates lots of go tooling goodies

How to :floppy_disk:


  • go >= 1.4.2
    • env vars $GOPATH, $GOROOT, $GOBIN
    • add $GOBIN to $PATH
  • vim >= 7.4 with lua
    # osx with lua
    brew reinstall vim --with-lua
    # ubuntu with scripting support
    sudo apt-get install vim-nox
  • spf13-vim and vim-go
  • my custom spf13 configuration
  • 3rd party go tools and dependencies

my custom spf13 configuration

spf-13 configuration files:

    ╰─○ ls -a | grep .vimrc
    .vimrc.before.local ←
    .vimrc.local ←
Either copy my files to $HOME adding a dot `.` before the name or if you already use spf13 append the content to your config files.

Install vim-go

Update spf13's bundles (aka vim plugins):

# precondition: spf13 go bundle group should have been enabled in
# .vimrc.before.local (done in my custom config file) in the previous step.
vim +BundleInstall! +BundleClean +q

# check out the install worked as expected
ls -l .vim/bundle | grep vim-go
drwxr-xr-x 17 gonzalo staff 578 oct 26 22:49 vim-go

update the 3rd party tools

# from vim

# from shell
gometalinter --install --update

TLDR; :sleeping:

vim-go integrations :suspect::electric_plug:

  • syntax check
  • snippets
  • tagbar support

  • godef
  • goimports

  • gofmt
  • govet
  • golint

  • go test
  • godoc
  • gorename

vim-go integrations :godmode::electric_plug:

  • oracle (manual)
    • callstack
    • callees
    • callers
    • callstack
    • describe
    • freevars
    • implements
    • peers
    • pointsto
    • referrers
  • gometalinter (supported linters)
    • interfacer
    • deadcode
    • gocyclo
    • varcheck
    • structcheck
    • aligncheck
    • errcheck
    • dupl
    • ineffassign

party time! :tada:

:w magic :sparkles:


the code is automatically formatted following
the official go code review comments

syntax checking

automatically build and highlight errors


used packages are automatically imported


of public names: exported functions, interfaces or structs from imported packages, or public struct methods. hint: type ctrl + space over a function to see its definition

code navigation

Navigate to definitions like a boss, even to the standard lib. hint: i have 2 maps: <C-]> to navigate in current buffer and <C-a> to navigate in a new tab

:GoTest, :GoTestCompile

Test you package, compile your test after refactor.


If you just need the documentation of the element over the cursor, type :GoDoc command.

snippets :clock1:

spf13 comes with the neocomplcache snippets plugin. Type the following characters, select the snippet and press <C-k> to go to the next step of the snippet.

  • forr: create for range loop
  • func: create function
  • meth: create method receiver
  • errn,: if err != nil { return something, err }
  • struct: create struct type
  • interface: create interface type
  • select: create select statement
  • test: create a test function
  • json: insert the json tag in a struct field

tagbar support :chocolate_bar:

view and navigate through the file structure

go oracle integration :older_woman: 1/2


Type it over a function definition to show in the quickfix window the possible callers of that function.


Type it over a function, method, struct... and see where is referenced. Very useful also for arguments and return types.


Type it over a struct and see what interfaces does that type implement.

go oracle integration :older_woman: 2/2


Shows an arbitrary path from the root of the call graph to the function containing the selection


Shows various properties: syntactic kind, type of an expression, value of a constant expression, the size, alignment, method set, and interfaces of a type, the declaration of an identifier...


type-safe rename of identifiers

Code linting

  • :Golint: runs golint to print style mistakes.
  • :GoVet: runs vet to spot errors not detected by the compiler.
  • :GoMetalinter: runs both previous linters and some more.

Gometalinter :hammer: 1/2

  • gofmt, govet, golint ✔
  • gotype: syntactic and semantic analysis similar to the Go compiler.
  • deadcode: finds unused code.
  • gocyclo: computes the cyclomatic complexity of functions.
  • goimports: checks missing or unreferenced package imports.

Gometalinter :hammer: 2/2

  • varcheck: find unused global variables and constants.
  • structcheck: find unused struct fields.
  • aligncheck: warn about un-optimally aligned structures.
  • errcheck: check that error return values are used.
  • dupl: reports potentially duplicated code.
  • ineffassign: detect when assignments to existing variables are not used.
  • interfacer: suggest narrower interfaces

config tips :page_with_curl:

let g:go_fmt_fail_silently = 1
let g:go_highlight_functions = 1
let g:go_highlight_methods = 1
let g:go_highlight_structs = 1
let g:go_highlight_operators = 1
let g:go_highlight_build_constraints = 1
let g:go_highlight_interfaces = 1
let g:go_term_enabled = 1
" let g:go_metalinter_autosave = 1
" autoimport ftw
let g:go_fmt_command = "goimports"
" go-def
au FileType go nmap  (go-def)
au FileType go nmap  (go-def-tab)
" default: ['vet', 'golint', 'errcheck']
" gotype does not work with non-installed packages
let g:go_metalinter_deadline = '20s'
let g:go_metalinter_enabled = ['golint', 'vetshadow', 'errcheck', 'ineffassign', 'vet', 'goimports', 'defercheck', 'aligncheck', 'dupl', 'gofmt', 'varcheck', 'gocyclo', 'testify', 'structcheck', 'deadcode']

ctrlp config :mag:

with Godep filtering

let g:ctrlp_root_markers = ['.ctrlp_go']
let g:ctrlp_user_command = {
  \ 'types': {
    \ 1: ['.ctrlp_go', 'cd %s && find ../ -type f -not -path "*/.git/*" -not -path "*/Godeps/*" -not -path "*/misc/package/dist_package/*"'],
    \ 2: ['.git/', 'cd %s && git ls-files . -co --exclude-standard'],
  \ }
\ }
Put an empty .ctrlp_go file in your project base directory to make CtrlP now show Godeps/ files.

other tips & tricks :dango:


Check out its featured plugins.


Get it here, it's really fast.


If you use it make sure the terminal preference
type is "xterm-256color"

os.Exit( :beer: )