Use golangci-lint with your lsp in neovim
When working with Go in Neovim, you want both gopls (the official Go LSP) and golangci-lint. gopls provides language features like autocomplete and go-to-definition, while golangci-lint-langserver acts as an LSP wrapper around golangci-lint to run multiple linters that catch issues gopls doesn’t.
TL;DR: Use Mason to install both
goplsandgolangci-lint-langserver. Configure them with nvim-lspconfig. They work together - gopls for language features, golangci-lint for comprehensive linting.
Install Neovim plugins
Using vim-plug, add these to your init.vim:
Plug 'williamboman/mason.nvim'
Plug 'williamboman/mason-lspconfig.nvim'
Plug 'neovim/nvim-lspconfig'
Run :PlugInstall to install them.
Install language servers with Mason
Open Neovim and run:
:MasonInstall gopls golangci-lint-langserver
Mason handles the installation and PATH management for you.
Configure both language servers
In your Neovim config (init.lua or in a separate lua file):
require("mason").setup()
require("mason-lspconfig").setup({
ensure_installed = { "gopls", "golangci_lint_ls" }
})
local lspconfig = require('lspconfig')
-- Setup gopls for Go language features
lspconfig.gopls.setup({
settings = {
gopls = {
analyses = {
unusedparams = true,
},
staticcheck = true,
},
},
})
-- Setup golangci-lint for comprehensive linting
lspconfig.golangci_lint_ls.setup({
init_options = {
command = { "golangci-lint", "run", "--out-format", "json" },
},
})
Configure golangci-lint rules
Create a .golangci.yml in your project root to customize which linters run:
linters:
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- unused
Now when you open a Go file, you get language features from gopls and linting from golangci-lint working together.
Legacy setup (manual installation)
If you’re not using Mason, you can install the tools manually with go install:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
go install github.com/nametake/golangci-lint-langserver@latest
Then configure nvim-lspconfig directly:
local lspconfig = require('lspconfig')
lspconfig.golangci_lint_ls.setup({
cmd = {'golangci-lint-langserver'},
root_dir = lspconfig.util.root_pattern('.git', 'go.mod'),
init_options = {
command = { "golangci-lint", "run", "--fast", "--out-format", "json" },
},
filetypes = {'go', 'gomod'}
})
When you open a Go file, nvim-lspconfig will dispatch to golangci-lint-langserver for linting. By default, it looks for .golangci.yml in your project root for linting configuration.
Summary
You need both gopls and golangci-lint for a complete Go development experience in Neovim. Use Mason to manage installations and nvim-lspconfig to configure them. gopls handles language features, golangci-lint runs multiple linters. They complement each other and work together seamlessly.