A minimal implementation of Golang development plugin written in Lua for Neovim.
Neovim (from v0.5) embeds a built-in Language Server Protocol (LSP) client. And Debug Adapter Protocol (DAP) are also brought into Neovim as a general debugger. With the power of them, we are able to easily turn Neovim into a powerful editor.
nvim-go
is designed to collaborate with them, provides sufficient features, and leverages community toolchains to get Golang development done.
:GoFormat
(via goimports
, gofmt
, gofumpt
and lsp
) when saving.:GoLint
(via revive
) automatically.:GoTest
, :GoTestFunc
, :GoTestFile
and :GoTestAll
. Generate test with :GoAddTest
.:GoGet
and :GoImport
.:GoAddTags
, :GoRemoveTags
, :GoClearTags
, :GoAddTagOptions
, :GoRemoveTagOptions
and :GoClearTagOptions
.:GoQuickType
(via quicktype
).:GoIfErr
(via iferr
).This section can be regarded as a guide or common practice to develop with nvim-go
, LSP (gopls
) and DAP.
If you are familiar with these tools or other equivalent, you may skip this chapter.
Language server provides vital language features to make Golang development easy.
We highly recommend you to use LSP client together with nvim-go
.
gopls
with neovim/nvim-lspconfig.vim.lsp.buf.declaration()
vim.lsp.buf.definition()
and vim.lsp.buf.type_definition()
vim.lsp.buf.implementation()
vim.lsp.buf.hover()
vim.lsp.buf.signature_help()
vim.lsp.buf.reference()
vim.lsp.buf.document_symbol()
and vim.lsp.buf.workspace_symbol()
vim.lsp.buf.rename()
vim.lsp.buf.format()
, also works with GoFormat
.vim.diagnostic
will also show lint issues with Virtual Text, which runs go/analysis
. You may disable auto_lint
if this works well with your project.For details of gopls
, please refer to https://github.com/golang/tools/blob/master/gopls/doc/design/design.md#features.
Prerequisites:
Install with your favorite package manager:
" dependencies
use('nvim-lua/plenary.nvim')
" nvim-go
use('crispgm/nvim-go')
" (optional) if you enable nvim-notify
use('rcarriga/nvim-notify')
" (recommend) LSP config
use('neovim/nvim-lspconfig')
Finally, run :GoInstallBinaries
after plugin installed.
Install
quicktype
withyarn
orpnpm
:
nvim-go
install quicktype
with npm
by default, you may replace it with yarn
or pnpm
.
require('go').config.update_tool('quicktype', function(tool)
tool.pkg_mgr = 'yarn'
end)
-- setup nvim-go
require('go').setup({})
-- setup lsp client
require('lspconfig').gopls.setup({})
require('go').setup({
-- notify: use nvim-notify
notify = false,
-- auto commands
auto_format = true,
auto_lint = true,
-- linters: revive, errcheck, staticcheck, golangci-lint
linter = 'revive',
-- linter_flags: e.g., {revive = {'-config', '/path/to/config.yml'}}
linter_flags = {},
-- lint_prompt_style: qf (quickfix), vt (virtual text)
lint_prompt_style = 'qf',
-- formatter: goimports, gofmt, gofumpt, lsp
formatter = 'goimports',
-- maintain cursor position after formatting loaded buffer
maintain_cursor_pos = false,
-- test flags: -count=1 will disable cache
test_flags = {'-v'},
test_timeout = '30s',
test_env = {},
-- show test result with popup window
test_popup = true,
test_popup_auto_leave = false,
test_popup_width = 80,
test_popup_height = 10,
-- test open
test_open_cmd = 'edit',
-- struct tags
tags_name = 'json',
tags_options = {'json=omitempty'},
tags_transform = 'snakecase',
tags_flags = {'-skip-unexported'},
-- quick type
quick_type_flags = {'--just-types'},
})
Display within Neovim with:
:help nvim-go
function! LintIssuesCount()
if exists('g:nvim_go#lint_issues_count')
return g:nvim_go#lint_issues_count
endif
endfunction
call airline#parts#define_function('nvim_go', 'LintIssuesCount')
call airline#parts#define_condition('nvim_go', '&filetype == "go"')
let g:airline_section_warning = airline#section#create_right(['nvim_go'])
function! LintIssuesCount()
if exists('g:nvim_go#lint_issues_count') && &filetype == 'go'
return g:nvim_go#lint_issues_count
endif
endfunction
let g:lightline = {
\ 'colorscheme': 'wombat',
\ 'active': {
\ 'left': [ [ 'mode', 'paste' ],
\ [ 'readonly', 'filename', 'modified', 'lintcount' ] ]
\ },
\ 'component_function': {
\ 'lintcount': 'LintIssuesCount'
\ },
\ }
require('hardline').setup({
-- ...
sections = {
{
class = 'error',
item = function()
if
vim.bo.filetype == 'go'
and vim.g['nvim_go#lint_issues_count'] ~= nil
then
return vim.g['nvim_go#lint_issues_count']
else
return ''
end
end,
},
-- ...
}
augroup NvimGo
autocmd!
autocmd User NvimGoLintPopupPost wincmd p
augroup END
Or equivalently:
local NvimGo = vim.api.nvim_create_augroup("NvimGo", {
clear = true,
})
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "NvimGoLintPopupPost",
group = NvimGo,
command = "wincmd p",
})