DEV Community

loading...
Cover image for How I Setup Go With Vim

How I Setup Go With Vim

Sophia Brandt
former tax officer turned programmer
Originally published at rockyourcode.com on ・3 min read

Language Server Support for Go in Vim

Last month I found a reddit thread about how to setup Vim for Go development.

The author uses coc.nvim, a heavy-weight plugin with external dependencies. coc.nvim ("Conqueror of Completion") offers powerful features, but you'll need to install Node.js.

If you prefer a more lightweight option that also work with plain Vim, this blog post might be for you.

Today I'm going to share my setup:

  • works with Vim and NeoVim
  • minimal external dependencies (gopls)
  • auto-completion support

Prerequisites

You should have a working installation of Go on your computer.

Install gopls, the official language server:

GO111MODULE=on go get golang.org/x/tools/gopls@latest
Enter fullscreen mode Exit fullscreen mode

Vim Setup

Vim needs a plugin for the Language Server Protocol.

I use prabirshrestha/vim-lsp, an asynchronous implementation that works both in Vim 8 and NeoVim. The plugin uses VimL and thus has no external dependencies.

Install with native package support or a plugin manager of your choice. Example:

cd ~/vim/pack
git submodule init
git submodule add https://github.com/prabirshrestha/vim-lsp.git
git add .gitmodules vim/pack/prabirshrestha/vim-lsp
git commit
Enter fullscreen mode Exit fullscreen mode

(I'm happy with vim-packager, but configuring it requires a bit more effort and time. The native package manager works well since Vim 8, but is a bit clunky.)

Let's wire up the language server with Go.

Create a new file in your Vim folder (~/vim/plugin/lsp.vim) with the following content:

func! s:setup_ls(...) abort
    let l:servers = lsp#get_allowed_servers()

    # key mappings
    for l:server in l:servers
        let l:cap = lsp#get_server_capabilities(l:server)

        if has_key(l:cap, 'completionProvider')
            setlocal completefunc=lsp#complete
        endif

        if has_key(l:cap, 'hoverProvider')
            setlocal keywordprg=:LspHover
        endif

        if has_key(l:cap, 'codeActionProvider')
            nmap <silent><buffer>ga <plug>(lsp-code-action)
        endif

        if has_key(l:cap, 'definitionProvider')
            nmap <silent><buffer>gd <plug>(lsp-definition)
            nmap <silent><buffer>gk <plug>(lsp-peek-definition)
        endif
    endfor
endfunc

# register language server
augroup LSC
    autocmd!
    autocmd User lsp_setup call lsp#register_server({
                \ 'name': 'gopls',
                \ 'cmd': {_->['gopls']},
                \ 'allowlist': ['go']
                \})

    autocmd User lsp_server_init call <SID>setup_ls()
    autocmd BufEnter * call <SID>setup_ls()
augroup END

# disable diagnostics etc.
let g:lsp_diagnostics_enabled                = 0
let g:lsp_diagnostics_signs_enabled          = 0
let g:lsp_diagnostics_virtual_text_enabled   = 0
let g:lsp_diagnostics_highlights_enabled     = 0
let g:lsp_document_code_action_signs_enabled = 0
Enter fullscreen mode Exit fullscreen mode

The first function creates key bindings if the language server runs. For example, hitting ga will give you "code actions". The most useful code action is auto-importing the necessary definitions. Code Actions are a feature I use a lot.

You can find a list of supported commands on the vim-lsp GitHub page.

Auto-completion?

Vim already has auto-completion out of the box.

Here is an excerpt from some extra key mappings in my ~/.vimrc ("stolen" from bluz71:

"-----------------------------
" completion mappings
"-----------------------------
"   t     - user defined completion (via completefunc setting)
inoremap <C-t>     <C-x><C-u>
Enter fullscreen mode Exit fullscreen mode

Now, when I want the language server to kick in to complete my Go code, I smash CTRL+T on my keyboard.

How to Format And Lint

The easiest way is to use the gofmt tool from the command-line. For example,

gofmt -w .
Enter fullscreen mode Exit fullscreen mode

The same goes for linting.

Install golint:

go install golang.org/x/lint/golint@latest
Enter fullscreen mode Exit fullscreen mode

Usage:

golint ./...
Enter fullscreen mode Exit fullscreen mode

Alternatively, you can install ALE. Here is an example setup which you can adjust for Go.

Conclusion

I've showed you a lightweight setup for Go and Vim. The above plugins and settings have served me well.

There are languages where I'd recommend a dedicated IDE (Java), but for Go I haven't felt the need yet.

Links

Discussion (3)

Collapse
citizen428 profile image
Michael Kohl

I went all in on nvim so I'm using the native LSP functionality now.

neovim.io/doc/user/lsp.html

My config can be found here:

github.com/citizen428/nvim-config

Collapse
sophiabrandt profile image
Sophia Brandt Author

I'm still on nvim 0.4, but as soon as I switch to 0.5, I'm going to give the native tree-sitter a shot.
Thanks for sharing your settings.

Collapse
citizen428 profile image
Michael Kohl

I'd highly recommend switching to one of the 0.5 nightlies if you're interested in nvim, most of the good stuff isn't in 0.4 and I'm not sure how soon we'll see a release. I run the nightlies on Windows, macOS, Ubuntu, and Arch and never had any problems with them FWIW.