
本文介绍如何通过正确配置 vim 和 vim-go 插件,使 go 源文件始终使用制表符(tab)进行缩进,避免保存时被自动重置为空格缩进。
默认情况下,vim-go 插件会主动管理 Go 文件的缩进行为(如 goimport、gofmt 等格式化工具调用),并强制启用 expandtab(即用空格模拟缩进),这会导致即使你手动执行 :setlocal noexpandtab | retab!,在保存或触发格式化后缩进仍被还原为空格。
要彻底解决该问题,不能仅依赖 ftplugin/go.vim 中的 setlocal noexpandtab —— 因为 vim-go 的格式化命令(如 :GoFmt)会在执行时临时覆盖本地设置;同样,:retab 仅修改现有空白字符,无法阻止后续自动缩进逻辑。
✅ 正确做法是:在 ~/.vimrc(或 ~/.config/nvim/init.vim)中全局禁用 expandtab 并为 Go 文件显式声明缩进规则,同时禁用 vim-go 的自动缩进干预:
" ~/.vimrc " 基础缩进策略:用 Tab 缩进,用空格对齐(推荐实践) set tabstop=4 set softtabstop=4 set shiftwidth=4 set noexpandtab " 关键:禁用空格缩进 set smarttab set shiftround " 对 Go 文件单独强化配置(在 filetype plugin 加载后生效) augroup go_indent_setup autocmd! autocmd FileType go setlocal noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 " 可选:禁用 vim-go 的自动格式化缩进覆盖(若使用 :GoFmt 或 :GoImport) autocmd FileType go let g:go_fmt_autosave = 0 autocmd FileType go let g:go_imports_autosave = 0 augroup END
⚠️ 注意事项:
- g:go_fmt_autosave = 0 并非关闭格式化,而是避免保存时自动触发 gofmt(它默认输出空格缩进)。你仍可手动运行 :GoFmt,但建议配合 gofumpt 或自定义 g:go_fmt_command 使用支持 Tab 的格式器(如 gofumpt -tab-width=4 -tabs=true);
- 若需保留 :GoFmt 的便利性又坚持 Tab 缩进,可改用 gofumports 或配置 g:go_fmt_command = 'gofumpt'(需提前安装);
- setlocal 必须在 FileType go 触发后执行(故用 autocmd),直接写在 ftplugin/go.vim 中可能因加载顺序被覆盖;
- 推荐阅读 Vim 社区经典方案:Indent with tabs, align with spaces,理解 tabstop/softtabstop/shiftwidth 协同机制。
完成配置后,重启 Vim(或执行 :source ~/.vimrc),新建或打开 .go 文件,输入 >> 或按 Tab 键即可插入真实 Tab 字符,:set expandtab? 应返回 noexpandtab,且保存后缩进保持不变。










