Featured image of post Go with Vim

Go with Vim

手把手教你配置Vim/Go开发环境

作为一个Vim深度用户,每接触一种新语言时,我都会为Vim配置好对应的开发环境,正所谓『工欲善其事,必先利其器』。

IMG_20231130_093158

安装Go

参考官方安装指导,这里就不多说了。

配置Go

Go的配置主要就是GOPATHPATH两个变量。GOPATH的默认值为$HOME/go,也就是Go会将软件安装到$HOME/go目录中,同时也是在$HOME/go中寻找软件依赖。

我个人喜欢将一些重要的东西隐藏起来,因此我们将$HOME/go变更为$HOME/.go

1
2
3
cd $HOME
mv go .go 
vim ~/.zshrc 

.zshrc中增加如下内容

1
2
3
4
5
if [ -d /usr/local/go ]; then
    export PATH=/usr/local/go/bin:$PATH
fi
export GOPATH=$HOME/.go
export PATH=$GOPATH/bin:$PATH

安装依赖

  • go install golang.org/x/tools/gopls@latest
  • go install github.com/jstemmer/gotags@latest
  • go install golang.org/x/tools/cmd/goimports@latest
  • go install github.com/fatih/motion@latest

安装vim-go

Vim插件管理有很多种,参考官方安装指导进行安装即可。

但我个人偏向于传统的直接安装方法,将vim-go项目中插件文件直接拷贝到.vim目录中。

1
2
3
4
5
6
cd path/to/vim-go
# 清理不需要的文件
/bin/rm -f * .* 2> /dev/null
/bin/rm -rf .github assets 
# 将文件拷贝到.vim
rsync -av ./ ~/.vim/

配置vim-go

官方的文档很多,但也很杂,而且都是英文的,阅读起来还是有点费力的。这里我们先对vim-go做个简单的配置,将vim-go的代码高亮与自动补全功能开启。

自动补全

这相信这个是大家最关心的内容。

1
2
let g:go_info_mode='gopls'
let g:go_def_mode='gopls'

这个我居然是在gopls项目中找到的,有点不可思议。

这里值得一说的是,自动补全依赖于你的TAB键,而这个可能由不同的插件管理着,如果你有问题,可以直接定义按键或设置插件到vim-go的自动补全函数go#complete#Complete(),但好在vim-go是将这个函数注册到omnifunc,可以直接使用快捷键<C-X><C-N>

比如我就是自己写的TAB插件,兼容omnifunc,因此vim-go直接装上就能用。官方文档就提到YouCompleteMevim-goTAB键上有冲突

代码高亮

1
2
3
4
5
6
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

为什么vim-go的代码高亮默认是关闭的,不是很理解!

高级功能

代码格式化/缩进 :GoFmt

vim-go使用gofmtgoimports进行代码格式化/缩进,当你保存文件时,这个过程就自动完成了。这个功能是自动开启的,如果你不喜欢这个功能可将其关闭。

1
2
" 停用自动格式化
let g:go_fmt_autosave = 0

gofmt OR goimports

1
let g:go_fmt_command = "goimports"

编译、运行、调试

  • :GoRun => go run => 运行整个包
  • :GoRun % => go run <current file>
  • :GoBuild => go build(有点差别) => 编译当前包
    • 不会生成目标文件
    • 如果有错误会打开quickfix窗口
  • :GoInstall
  • :GoTest

为了更好的配合vim-go,我们可以开启vim的文件自动保存功能:

1
set autowrite

在编译时,我们的代码可能会存在错误,vim-go会自动打开一个quickfixlocation lists错误窗口,这里大家可以根据自己的偏好选择:

1
let g:go_list_type = "quickfix"

官方说明

按键绑定

官方版

1
2
3
autocmd FileType go nmap <leader>b  <Plug>(go-build)
autocmd FileType go nmap <leader>r  <Plug>(go-run)
autocmd FileType go nmap <leader>t  <Plug>(go-test)

但实际nmap <buffer>可能会更好一些。因为我们vim里面打开的可能还有其他类型的文件

1
2
3
autocmd FileType go nmap <buffer> gb  <Plug>(go-build)
autocmd FileType go nmap <buffer> gr  <Plug>(go-run)
autocmd FileType go nmap <buffer> gt  <Plug>(go-test)

我们常用的以g开头的快捷键gg(跳转到文件开头),这里定义vim-go快捷键时,不要与之冲突就好。

TODOgb - 编译当前文件,gB - 编译当前包,这样可能会更好。后面有合适代码再尝试一下

Go对于普通文件和测试文件的处理命令是不一样的,所以这里需要区分一下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
" run :GoBuild or :GoTestCompile based on the go file
function! s:build_go_files()
  let l:file = expand('%')
  if l:file =~# '^\f\+_test\.go$'
    call go#test#Test(0, 1)
  elseif l:file =~# '^\f\+\.go$'
    call go#cmd#Build(0)
  endif
endfunction

autocmd FileType go nmap <leader>b :<C-u>call <SID>build_go_files()<CR>

代码跳转

我相信这个是高级功能中大家最在意的。vim-go不仅支持本地跳转,而且支持跳转到外部代码,比如标准库和GOPATH中的第三方库。

  • :GoDef - 跳转到当前类型的定义 - 快捷键<C-]>
  • :GoDefPop - 返回跳转前的位置 - 快捷键<C-t><C-o>
  • :GoDefStack - 显示当前的跳转列表
  • :GoDefStackClear - 清除当前的跳转列表

其他

vim-go是个很强大的插件,还有其他一些高级功能待探索。

代码片段补全 / snippets

UltiSnips vs neosnippet:

  • UltiSnips使用python,需要vim有python支持
  • neosnippet使用vim脚本,原生支持

试用了一下UltiSnips,发现其抢注TAB快捷键,虽然可以修改,但总感觉不是滋味,放弃了。

安装neosnippet

1
2
3
4
5
# 清理不需要的文件
rm -f * .*
rm -rf .github test denops 
# 安装
rsync -av ./ ~/.vim/

对比UltiSnipsneosnippet就安分多了: IMG_20231130_115125

接下来我们就配置快捷键。

1
2
imap <C-o>     <Plug>(neosnippet_expand_or_jump)
smap <C-o>     <Plug>(neosnippet_expand_or_jump)

官方是用<C-k>按键,但我们的<C-k>是用来在窗口间跳转,所以改成了<C-o>

注意:插入模式下绑定快捷键并不是一件容易的事。插入模式下,快捷键受终端软件和桌面版Vim的影响,两者都可能截取键盘按键。所以需要在当前环境下测试,并且很可能在其他环境下无法使用。比如在我的环境中<C-i>就无法正常工作。

当然我们也可以借助类似SuperTab的插件来实现TAB键补全,进一步的配置可参考官方

安装模板

You must install neosnippet-snippets or disable runtime snippets.

如果看到如上错误,说明neosnippets缺少模块。

代码片段补全依赖于模板,可以从neosnippet-snippetsvim-snippets下载自己需要的模板安装。前者是neosnippet格式,后者是snipMate格式(需要格外配置)。

1
2
3
4
5
6
mkdir ~/.vim/{neosnippets,snippets}
# 下载需要的模板并放入正常的文件夹
cd ~/.vim/neosnippets
wget https://raw.githubusercontent.com/Shougo/neosnippet-snippets/master/neosnippets/go.snip
cd ~/.vim/snippets
wget https://raw.githubusercontent.com/honza/vim-snippets/master/snippets/go.snippets

开启snipMate格式兼容

1
let g:neosnippet#enable_snipmate_compatibility = 1

vim-go已经自带一个snipMate格式模板,如果喜欢这个模块,将其链接到snippets文件夹:

1
2
cd ~/.vim/snippets
ln -svf ../gosnippets/snippets/go.snip .

最后更新于 2023-12-13
小酌怡情
Built with Hugo
主题 StackJimmy 设计
访问量 -    访客数 - 人次