DEV Community

Cover image for How to set up Vim for Go Development
Preslav Mihaylov
Preslav Mihaylov

Posted on • Originally published at pmihaylov.com

How to set up Vim for Go Development

One of the major reasons I love programming in Go is that I can do it in any IDE or editor I want, including my favourite Vim editor.

Unlike Java, for example, which is highly coupled to IntelliJ or Eclipse, Go is much more lightweight and the tools you use with it can be integrated with any editor.

In this guide, I will help you setup your Vim as a fully-fledged Go IDE, including the plugins you need to install but also setting up the important options & mappings which you'll use daily.

Prerequisites

You'll need to have Go installed & your Go environment setup, namely your $GOPATH and related subdirectories - /bin /pkg /src.

You'll also need to use nvim instead of vim or have your vim updated to version 8+.

The Main Vim plugin for Go

One of the only plugins you need for Go is called vim-go. It aggregates all the tools you need to get started with Go development.

To install it via pathogen:

git clone https://github.com/tpope/vim-pathogen ~/.vim/bundle

Other installation options.

After you've installed it, you can customise it using these options which are highly opinionated, but work best for me:

" disable all linters as that is taken care of by coc.nvim
let g:go_diagnostics_enabled = 0
let g:go_metalinter_enabled = []

" don't jump to errors after metalinter is invoked
let g:go_jump_to_error = 0

" run go imports on file save
let g:go_fmt_command = "goimports"

" automatically highlight variable your cursor is on
let g:go_auto_sameids = 0

For syntax highlighting, use these options:

let g:go_highlight_types = 1
let g:go_highlight_fields = 1
let g:go_highlight_functions = 1
let g:go_highlight_function_calls = 1
let g:go_highlight_operators = 1
let g:go_highlight_extra_types = 1
let g:go_highlight_build_constraints = 1
let g:go_highlight_generate_tags = 1

Finally, install all the required go tools by opening vim and running:

:GoInstallBinaries

coc.nvim - Autocompletion & linting

In the past, I've relied on YouCompleteMe for auto-completion or vim-go's native integration with vim for auto-completion & ALE for linting/static code analysis.

Nowadays, I prefer using coc.nvim and its plugins to do all that as I've found it to be more reliable than all of those tools.

For installation instructions, follow the Quick Start guide.

After you've installed it, run this command to install the necessary coc extension for Go:

vim -c 'CocInstall -sync coc-go coc-html coc-css coc-json|q'

The html/css/json extensions are optional but who doesn't deal with those nowadays. You'd probably need them at some point.

Afterwards, open vim & type :CocConfig to open coc's configuration file. These are my opinionated settings, stripped from the non-go related settings:

{
  "suggest.noselect": false,
  "diagnostic.errorSign": "✘",
  "diagnostic.warningSign": "!",
  "diagnostic.infoSign": "?",
  "diagnostic.checkCurrentLine": true,
  "coc.preferences.formatOnSaveFiletypes": [
    "javascript",
    "html",
    "json",
    "css",
    "scss",
    "go"
  ],
  "coc.preferences.hoverTarget": "float",
  "languageserver": {
    "golang": {
      "command": "gopls",
      "rootPatterns": ["go.mod"],
      "filetypes": ["go"]
    }
  },
  "go.goplsOptions": {
    "staticcheck": true
  }
}

For all auxiliary coc settings, add these settings to your .vimrc.

Mappings For The Most Useful Commands

Having great tools is not enough. You need to know how to use them. Hence, it is best to customize some of the mappings which vim-go and coc provide you so that you're more effective when dealing with Go code.

Here are the mappings I use most often and the way I've configured them:

Manage unit tests in the current file

I've mapped running all the tests in the current file to <leader>-t which translates to \ + t on my Mac & Linux.

autocmd BufEnter *.go nmap <leader>t  <Plug>(go-test)

I've also mapped \ + tt to run the current test function only, instead of running all of them:

autocmd BufEnter *.go nmap <leader>tt <Plug>(go-test-func)

Finally, I use \ + c to toggle the coverage profile for the current file I'm in:

autocmd BufEnter *.go nmap <leader>c  <Plug>(go-coverage-toggle)

Inspect a Go Codebase

Show the function signature for a given routine with \ + i:

autocmd BufEnter *.go nmap <leader>i  <Plug>(go-info)

Show the interfaces a type implements with \ + ii:

autocmd BufEnter *.go nmap <leader>ii  <Plug>(go-implements)

Describe the definition of a given type with \ + ci:

autocmd BufEnter *.go nmap <leader>ci  <Plug>(go-describe)

See the callers of a given function with \ + cc:

autocmd BufEnter *.go nmap <leader>cc  <Plug>(go-callers)

Find all references of a given type/function in the codebase with \ + cr:

nmap <leader>cr <Plug>(coc-references)

Go to definition/Go back with Ctrl+d and Ctrl+a:

nmap <C-a> <C-o>
nmap <C-d> <Plug>(coc-definition)

Refactor Go Code

Not many options here, but there's renaming the symbol your cursor is on with \ + r:

nmap <leader>r <Plug>(coc-rename)

Occasional Maintenance of Tooling

To update all Go tools, run this from vim:

:GoUpdateBinaries

And updating all coc plugins:

:CocUpdate

To upgrade vim-go or coc.nvim, delete the folders from ~/.vim/bundle and git clone the repos again.

Setup The Cool gruvbox Theme (Optional)

Install gruvbox using pathogen:

git clone https://github.com/morhetz/gruvbox ~/.vim/bundle

Enable it in your .vimrc with some opinionated extra options:

colorscheme gruvbox
autocmd ColorScheme * highlight CocErrorFloat guifg=#ffffff
autocmd ColorScheme * highlight CocInfoFloat guifg=#ffffff
autocmd ColorScheme * highlight CocWarningFloat guifg=#ffffff
autocmd ColorScheme * highlight SignColumn guibg=#adadad

Want to see how it looks?

Setup tmux For Terminal Multiplexing (Optional)

If you want to manage multiple terminal tabs in the same window, use tmux (See my how to guide):

This is one of the most useful tools I have setup because it allows me to do my code editing in vim and manage all sorts of other terminal-related tasks in separate tabs all inside the same window.

Conclusion

And that's everything I use for my daily Go programming.

This setup has worked extremely well for me and have in mind that I'm also dealing with Uber's huge Go Monorepo, where I've been able to integrate my vim environment seamlessly (with some extra settings which you probably won't need.

If you want to see my entire vim development environment, check out all my dotfiles and default-setups repos, which include my full setup, including external programs, the terminal, vim, tmux, colorschemes, etc.

Happy Gophing!

Check out some of my other Go series:
Integrating your Go Service with ELK
gRPC With Go Crash Course

Top comments (0)