As a Go developer who spends most of the day in the terminal, I’ve invested time in crafting a Neovim setup that rivals full-featured IDEs. Here’s how I configured Neovim for serious Go development.

LSP Integration

The foundation of my setup is gopls, the official Go language server. I use nvim-lspconfig for easy configuration:

require('lspconfig').gopls.setup({
  settings = {
    gopls = {
      analyses = {
        unusedparams = true,
        shadow = true,
      },
      staticcheck = true,
      gofumpt = true,
    },
  },
})

This setup gives me:

  • Code completion
  • Signature help
  • Go-to-definition
  • Find references
  • Diagnostics (including staticcheck integration)

Code Completion

For completion, I use nvim-cmp with several sources:

  • luasnip for snippets
  • nvim_lsp for LSP completions
  • buffer for text from other buffers
  • path for file paths

Testing Integration

I created a custom plugin called nvim-dbee for database management, but for Go tests, I rely on vim-test with a custom wrapper:

let test#go#gotest#executable = 'go test -v -count=1'

Running tests is as simple as :TestFile or :TestNearest.

Debugging

Debugging Go in Neovim is surprisingly smooth with nvim-dap and delve:

require('dap-go').setup()

Set breakpoints with DapToggleBreakpoint, start debugging with DapContinue, and step through code with DapStepOver.

Key Mappings

My most-used mappings:

nnoremap <leader>gd :lua vim.lsp.buf.definition()<CR>
nnoremap <leader>gr :lua vim.lsp.buf.references()<CR>
nnoremap <leader>ca :lua vim.lsp.buf.code_action()<CR>
nnoremap <leader>rn :lua vim.lsp.buf.rename()<CR>
nnoremap <leader>tf :TestFile<CR>

Why This Works for Me

This setup keeps me in the terminal while providing all the features I need. The learning curve was worth it—my workflow is faster and more efficient than it ever was with VS Code or GoLand.

The key is starting simple: LSP first, then add completion, testing, and debugging incrementally. Don’t try to replicate an IDE feature-for-feature on day one.