我為什麼會選擇Vim來開發Go專案及Vim IDE安裝配置和操作

孔令飞發表於2024-04-05

你好,我是孔令飛,位元組跳動雲原生資深研發、前騰訊雲原生技術專家。《企業級 Go 專案開發實戰》、《從零開發企業級 Go 應用》作者,歡迎加入 孔令飛的雲原生實戰營,助你進階 Go + 雲原生高階開發工程師。

作為一名 Golang 開發,你需要一個編輯器來完成你日常的程式碼編寫。在編寫程式碼過程中,會有一些高頻、重要的程式碼開發操作需要去執行,例如:檢視函式的定義、快速的跳轉到上一次開啟的檔案、程式碼補全等。這些操作如果能用工具來自動完成,或者提供一種高效的方式協助我們去完成,那麼我們的開發效率會大大提高。

當這些功能聚集在一個編輯器中,我們就可以稱這個編輯器為IDE(整合開發環境,Integrated Development Environment)了。

所以,為了提高程式碼開發效率,我們需要的是一個包含了基本程式碼編輯功能的 IDE。當前有很多優秀的 IDE 可供我們去開發 Go 程式碼:

  • Visual Studio Code: Visual Studio Code是一個輕量級的、跨平臺的程式碼編輯器,它支援Golang的開發。它具有豐富的外掛生態系統,可以透過安裝Go相關的外掛來提供程式碼編輯、除錯、自動完成等功能;
  • GoLand: GoLand是由JetBrains開發的專為Golang開發而設計的IDE。它提供了一套完整的工具和功能,包括程式碼編輯、除錯、自動完成、程式碼導航等。GoLand還具有強大的程式碼分析和重構功能,可以幫助開發人員提高程式碼質量和效率;
  • LiteIDE: LiteIDE是一個專門為Golang開發者打造的輕量級IDE。它提供了簡潔的介面和直觀的操作,支援程式碼編輯、除錯、自動完成等功能。LiteIDE還具有程式碼導航、專案管理和快速構建等實用工具;
  • Sublime Text: Sublime Text是一個流行的跨平臺程式碼編輯器,也可以用於Golang開發。它具有簡潔的介面和豐富的外掛生態系統,可以透過安裝相關外掛來提供Golang的程式碼編輯和除錯功能;
  • Atom: Atom是由GitHub開發的免費、開源的程式碼編輯器,也可以用於Golang開發。它具有可定製的介面和豐富的外掛生態系統,可以透過安裝相關外掛來提供Golang的程式碼編輯、除錯和自動完成功能;
  • Vim: Vim是一個高度可定製的文字編輯器,廣泛用於程式碼編輯和開發。它具有強大的編輯功能和快捷鍵,可以透過安裝外掛和配置檔案來提供程式碼高亮、自動完成、程式碼導航等功能。Vim還支援Golang的開發,可以透過安裝相關外掛來提供Golang的程式碼編輯和除錯功能;
  • Emacs: Emacs是一個可擴充套件的文字編輯器,也用於程式碼開發。它具有強大的編輯功能和內建的Lisp程式設計環境,可以透過安裝外掛和配置檔案來提供程式碼高亮、自動完成、程式碼導航等功能。Emacs也支援Golang的開發,可以透過安裝相關外掛來提供Golang的程式碼編輯和除錯功能。

這些IDE都具有不同的特點和功能,你可以根據自己的需求和偏好選擇適合自己的IDE。無論選擇哪個IDE,掌握其功能和工具,熟練使用它們,都能提高Golang程式碼開發的效率和質量。

可以看到 IDE 有很多,當前最受環境的 IDE 是 GoLand,也是我很喜歡的 IDE。但日常開發中,我使用的是 Vim IDE。

為什麼選擇 VIM?

提示:蘿蔔白菜各有所愛,你覺得用著舒服的 IDE 就是最好的 IDE。這裡,不是辯論哪個 IDE 更好,而是來分享下,我在選擇 IDE 的一些思考過程。

這裡,先來解釋下,我為什麼會選擇 Vim IDE。先來看下我的開發環境,如下圖所示:

開發環境示意

首先,公司為了網路安全,會至少隔離出以下 3 種網路:

  • 開發網(Development Network):開發網是專門用於軟體開發和測試的網路環境。在開發網中,開發人員可以進行軟體開發、除錯和測試,並與其他開發人員共享程式碼和資源。開發網通常與外部網路隔離,以保護敏感的開發和測試環境,同時提供更高的安全性和靈活性;
  • 辦公網(Office Network):辦公網是企業或組織內部員工進行日常辦公和業務活動的網路環境。在辦公網中,員工可以訪問共享檔案、電子郵件、內部網站和其他辦公應用程式。辦公網通常連線到網際網路,以便員工可以與外部網路進行通訊和訪問;
  • 生產網(Production Network):生產網是用於生產環境和業務執行的網路環境。在生產網中,企業或組織的主要業務應用程式和服務執行,並提供對外服務。生產網的穩定性和安全性非常重要,因為它直接影響到業務的正常執行和資料的安全性。

通常一個開發中的服務/元件,需要訪問公司內的其他服務,這些服務可能是公共服務,也可能是其他非公共服務。這些測試服務都是部署在開發網中的。所以,如果你的服務,想要具有一個完整的測試環境,就一定需要部署到開發網中。

如果你的辦公機和開發機不是同一臺機器,勢必會需要同步辦公機中的程式碼到開發機或者辦公機中的構建產物到開發機,那麼這就會遇到以下 2 個問題:

  1. 違背了不重複造輪子的哲學:作為一名開發者,不重複造輪子應該是我們一直需要去遵守的哲學,不衝突造輪子,會使事情變得更易維護、效率更高;
  2. 程式碼不一致:因為需要雙向同步,可能就會因為網路抖動,開發 IDE 異常、人為操作等原因,造成遠端和本地的程式碼不一致,從而帶來一些其他問題,降低開發效率。

上面的 2 個原因,造成我想直接基於開發網的的開發機去開發程式碼,但這還不足以說服自己。這裡,再來從另一個方面解釋下,我為什麼要直接在開發機開發程式碼。

開發程式碼通常包含很多工作,例如:程式碼編寫、程式碼編譯、程式碼部署等。我們需要儘可能提高每個流程的開發效率,只有這樣整個開發效率才會很高。本地開發機,可能會提供很多效率工具來提高我們的開發效率,但是最能提高開發效率的可能是 Linux 作業系統自帶或者可以安裝的各類工具,例如:Bash、AWK、Sed、Makefile、Find 等工具。Linux 作業系統中非常豐富的工具、便捷高效的命令列操作方式、以及可程式設計、靈活的運維指令碼語言 Shell 等,都可以極大提高我們的開發效率。

基於以上原因,我比較傾向於選擇 Vim。但是 Vim 相比於其他 IDE 的上手難度、功能缺失、操作複雜度,又讓我覺得 Vim 不夠完美。

我試圖尋找更完美的解決方案,例如:使用 Goland 的 SSH 遠端開發模式,在本地開發程式碼,實時同步到開發機中的原始碼目錄。Goland的遠端開發模式,透過部署在開發機上的 agent,跟本地 Goland 客戶端進行通訊,程式碼用的都是同一份,雖然解決重複造輪子的問題,但是在使用過程中,也發現了其他一些問題:

  1. 受限於網路連線的穩定性,在啟動Goland SSH 專案的時候,經常會卡死;
  2. Goland 中的搜尋和操作只能侷限在專案內,如果你想跳轉到專案外進行一些操作和搜尋,就實現不了;
  3. 總是會遇到一些未知問題,導致程式碼跳轉失效。

所以,基於以上原因,我覺得用 Goland 不是一個好的方法,又將目光轉回 Vim 中。這時候,我在想,如果能將 Vim 配置成跟Goland 一樣好用,就完美了。我思考了一下我開發過程中常用的操作,發現這些操作,都可以透過 Vim 的各類外掛來完成,並且從功能、易用性上能夠跟 Goland 相媲美。

所以,基於我的開發環境、需求等,我最終選擇了使用 Vim IDE。那麼接下來我就來介紹下,如何安裝,並配置 Vim 為一個順手的 Go 程式碼開發 IDE。

安裝 Vim 9

如果你當前的 Linux 發行版,已經安裝了 Vim 9,可跳過 Vim 9 的安裝。如果沒有安裝 Vim 或者版本不是 9,建議升級到 Vim 9。安裝命令如下:

$ git clone https://github.com/vim/vim /tmp/vim
$ cd /tmp/vim
$ sudo apt install -y libncurses5-dev
$ CFLAGS="-I/usr/local/include -fPIC" ./configure --prefix=/usr/local --with-features=huge --enable-cscope --enable-multibyte --enable-rubyinterp --enable-perlinterp --enable-python3interp --enable-luainterp --with-tlib=ncurses --without-local-dir
$ make
$ sudo make install
$ echo "alias vi=/usr/local/bin/vim" >> ~/.bash_aliases # 設定 vi 為最新的 vim 版本
$ bash

Vim IDE 安裝和配置

上面,我們安裝好了 Vim 編輯器。接下來,就可以安裝 Vim IDE,具體安裝命令如下:

$ rm -rf $HOME/.vim; mkdir -p ~/.vim/pack/plugins/start/
$ git clone https://github.com/colin404/vim-go ~/.vim/pack/plugins/start/vim-go
$ git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim
$ git clone --depth=1 https://github.com/colin404/vimrc.git ~/.vim_runtime
$ sh ~/.vim_runtime/install_awesome_vimrc.sh
$ git clone https://github.com/superproj/vimrc /tmp/vimrc # 安裝自定義 Vim 配置
$ cp /tmp/vimrc/vimrc $HOME/.vim_runtime/my_configs.vim

在之前使用 Vim 的過程中,發現依賴的倉庫,例如:fatih/vim-goamix/vimrc 最新版本會有一些 Bug 或環境不適配,導致 Vim IDE 配置失敗。為了提高你的配置成功率,我 Fork 了一份穩定版本。上面安裝配置,是從我 Fork 出來的(colin404/vim-gocolin404/vimrc)、經過驗證(Debian 12)的程式碼倉庫來安裝的。當然,我會定期跟上游進行程式碼同步,確保 Fork 出來的程式碼倉庫,功能上能跟最新的上游對齊。

提示:https://github.com/superproj/vimrc 是我的 vimrc 配置。

Vim 基礎語法介紹

後面,我會介紹如何配置 Vim 使其成為一個順手的 IDE,這就需要我們瞭解如何配置 Vim。Vim 使用 vimrc 檔案來配置。

.vimrc 檔案是 Vim 的配置檔案,用於個性化和定製 Vim 編輯器的行為。它是一個文字檔案,位於使用者的主目錄下(在 Linux 和 macOS 系統中是 $HOME/.vimrc,在 Windows 系統中是 $HOME/_vimrc$HOME/vimfiles/vimrc)。

.vimrc 檔案中包含了一系列的 Vim 命令,用於設定編輯器的各種選項和功能。以下是一些常見的 .vimrc 配置語法:

  1. 設定選項:使用 set 命令來設定 Vim 的選項。

例如,要設定縮排為 4 個空格:

set tabstop=4
set shiftwidth=4
set expandtab
  1. 對映按鍵:使用 mapnnoremapinoremap 指令將一個按鍵繫結到某一個操作上。

.vimrc 配置檔案中,有三個常用的按鍵對映指令:mapnnoremapinoremap,它們分別用於建立遞迴對映、非遞迴對映和插入模式下的對映。

  • map 指令
    map 指令用於建立遞迴對映,它將按鍵對映到一個命令,並且可以被其他對映所影響。它的語法如下:
map {lhs} {rhs}

其中,{lhs} 是按鍵的左手邊(left-hand side),{rhs} 是按鍵的右手邊(right-hand side),表示按下左手邊的按鍵時執行右手邊的命令。例如,下面的命令將 <F2> 鍵對映到儲存檔案的命令:

map <F2> :w<CR>

當按下 <F2> 鍵時,將會執行 :w<CR> 命令來儲存檔案。
請注意,map 指令建立的按鍵對映是遞迴的,這意味著它可以被其他對映所影響。這可能會導致按鍵對映衝突和意外行為。

  • nnoremap 指令
    nnoremap 指令用於建立非遞迴對映。語法和 map 指令一致。請注意,nnoremap 指令建立的按鍵對映是非遞迴的,這意味著它不會被其他對映所影響。這在避免按鍵對映衝突和意外行為方面非常有用。
  • inoremap 指令
    inoremap 指令用於建立插入模式下的對映,它將按鍵對映到一個文字字串,並且只在插入模式下生效。語法和 map 指令一致。請注意,inoremap 指令建立的按鍵對映只在插入模式下生效,這意味著它不會影響普通模式下的按鍵對映。

在使用這些指令時,請注意避免按鍵對映衝突和意外行為。

另外,可以使用 unmap 指令來取消一個按鍵對映,例如:

unmap <F10>
  1. 定義函式:使用 function 命令來定義函式。例如,定義一個函式來刪除當前行並儲存檔案:
function! DeleteAndSave()
    execute "normal! dd"
    write
endfunction
  1. 自動命令:使用 autocmd 命令來定義自動命令。例如,定義一個自動命令,在儲存檔案時自動執行 Go 程式碼格式化工具:
autocmd BufWritePre *.go :silent! GoFmt
  1. 條件語句:使用 if 語句來根據條件執行不同的命令。例如,如果檔案型別是 Markdown,則設定文字寬度為 80 個字元:
if &filetype == 'markdown'
    set textwidth=80
endif
  1. 註釋:使用 " 符號來新增註釋。例如:
" 這是一個註釋

這只是 Vim 指令碼語言的一小部分。您可以在 Vim 的幫助文件中找到更多關於配置語法和命令的詳細資訊。要使新的 .vimrc 配置生效,可以重新啟動 Vim,或者在 Vim 中輸入以下命令重新載入配置:

:source ~/.vimrc

Vim IDE 外掛配置

提示:我根據自己的操作習慣,自定義了一些個人喜歡的按鍵操作,你可以根據按鍵設定方法,設定為自己喜歡的按鍵。

這裡,先來看下,在進行 Go 程式碼開發的過程中,通常需要進行哪些類別的操作:

  • 程式碼編輯:基本的程式碼編輯操作;
  • 程式碼跳轉:跳轉到函式定義、型別定義等處;
  • 檔案檢視:檢視檔案列表,例如:最近訪問的檔案列表、專案根目錄下的所有檔案列表等;
  • 緩衝區操作:在編輯程式碼的過程中,會開啟多個檔案,這些檔案內容都放在 Vim 緩衝區中,需要經常切換緩衝區,檢視已開啟的檔案;
  • 字串查詢:在當前目錄下查詢指定的字串並跳轉到指定位置。
  • 視窗操作:關閉、移動游標到新視窗等操作。

接下來,我們來看下,這些功能如何在 Vim 中較好的實現。

程式碼編輯

Vim 編輯器本身 提供了基本的、高效說的程式碼編輯功能。

程式碼跳轉

可以使用 vim-go 的程式碼跳轉功能來完成 Go 程式碼跳轉等功能。

vim-go 是一個專門為 Go 語言開發者設計的 Vim 外掛,它提供了一系列的功能和工具,以提高 Go 語言開發的效率和舒適度。以下是 vim-go 外掛的一些主要功能:

  • 程式碼自動補全:vim-go 外掛整合了 gocode,可以實現 Go 程式碼的自動補全功能。它可以根據當前上下文提供變數、函式、結構體等的補全建議。
  • 程式碼導航:vim-go 外掛支援快速跳轉到函式定義、變數宣告和型別定義等。透過使用gd命令可以跳轉到游標下的識別符號的定義,使用gD命令可以跳轉到識別符號的宣告。
  • 文件檢視:vim-go 外掛可以方便地檢視 Go 程式碼的文件。透過使用K命令可以在 Vim 中檢視當前游標下識別符號的文件。
  • 程式碼重構:vim-go 外掛提供了一些程式碼重構的功能,如重新命名變數、提取函式、提取介面等。這些功能可以幫助開發者快速進行程式碼重構操作。
  • 單元測試:vim-go 外掛支援執行和除錯 Go 程式碼的單元測試。透過使用:GoTest命令可以執行當前檔案的單元測試,使用:GoTestFunc命令可以執行當前游標下的測試函式。
  • 程式碼格式化:vim-go 外掛可以根據 Go 語言的官方程式碼格式規範自動格式化程式碼。透過使用:GoFmt命令可以格式化整個檔案,使用:GoImport命令可以自動匯入缺失的包。
  • 構建和執行:vim-go 外掛提供了一些命令來構建和執行 Go 程式碼。透過使用:GoBuild命令可以構建當前檔案,使用:GoRun命令可以執行當前檔案。
  • 程式碼分析:vim-go 外掛整合了 golint、govet、gotype 等工具,可以對 Go 程式碼進行靜態分析,提供程式碼質量和錯誤檢查。

檢視安裝方式如下:

Plugin 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }

vim-go 提供了很多函式用來完成程式碼跳轉,你可以將這些函式繫結到快捷鍵,使用快捷鍵進行快速跳轉。

檔案檢視

可以使用 Vim fzf 外掛來完成檔案檢視等功能。

fzf(Fuzzy Finder)是一個強大的命令列模糊查詢工具,可以快速在大量資料中進行模糊搜尋。fzf 外掛是將 fzf 整合到 Vim 中的外掛,可以使 Vim 的檔案、緩衝區、標籤等搜尋更加高效和便捷。

外掛安裝方式如下:

Plugin 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
Plugin 'junegunn/fzf.vim'

fzf 外掛提供很多功能,比較重要的功能列表如下:
FZF指令

fzf 外掛預設只在當前目錄中進行查詢,但日常開發中,我們進行查詢時,可能經常期望在整個專案進行查詢,所以這裡,我們可以透過使用 vim-rooter 外掛,來自動根據當前開啟的檔案,確定專案的根目錄,並將 Vim 的當前工作目錄設定為專案根目錄。

可以透過以下方式安裝 vim-rooter 外掛:

Plugin 'airblade/vim-rooter'

為了便於使用這些按鈕,我們配置成快捷鍵:

nnoremap <leader>f :RG<cr>
nnoremap <leader>r :History<cr>
nnoremap <leader>j :Buffers<cr>
nnoremap <leader>k :Files<cr>
nnoremap <leader>l :cd %:p:h<cr>:Files<cr>
nnoremap <leader>t :Tags<cr>

" 使用 <leader> 鍵不便於單手操作,為了提高操作效率,我又進行了以下按鍵對映:
nnoremap <C-Q> :RG<cr>
nnoremap <C-R> :History<cr>
nnoremap <C-E> :Buffers<cr>
nnoremap <C-K> :Files<cr>

注意,這裡的 <leader> 鍵,我們配置的是空格鍵:

nnoremap <SPACE> <Nop>
map <Space> <Leader>

此外,為了更方便的使用 fzf,還需要進行一些配置:

let g:fzf_preview_window = ['right:hidden', 'ctrl-/']
let g:fzf_layout = {'up':'~90%', 'window': { 'width': 0.8, 'height': 0.8,'yoffset':0.5,'xoffset': 0.5, 'highlight': 'Todo', 'border': 'rounded' } }
" [Buffers] Jump to the existing window if possible
let g:fzf_buffers_jump = 1
"let g:fzf_action = { 'ctrl-c': ['abort', 'cancel'] }
" [[B]Commits] Customize the options used by 'git log':
let g:fzf_commits_log_options = '--graph --color=always --format="%C(auto)%h%d %s %C(black)%C(bold)%cr"'
" [Tags] Command to generate tags file
let g:fzf_tags_command = 'ctags -R'

之後,我們就可以在 Vim 中鍵入 <leader> + r 來檢視最近開啟的檔案和緩衝區:
檢視最近開啟的檔案和緩衝區

可透過鍵入 <leader> + k 來在當前專案中查詢檔案:
當前專案中查詢檔案

緩衝區操作

我們可以使用 fzf 提供的 :Buffers 指令,來檢視當前開啟的緩衝區。例如,鍵入 <leader> + j 來檢視當前開啟的緩衝區:
檢視當前開啟的緩衝區

另外,還可以使用以下快捷鍵,來執行各類緩衝區出操作:

快捷鍵 功能
Ctrl + w, c 關閉當前緩衝區

字串查詢

我們可以使用 fzf 提供的 :RG 指令,來在當前專案目錄中指定字串查詢。例如,鍵入 <leader> + f 來查查詢指定的字串:
查詢指定的字串

視窗操作

可以執行以下快捷鍵來執行各類視窗操作
視窗操作快捷鍵

快捷鍵對映

上面,我們配置了 Vim IDE,也對映了一些按鍵,為了方便你統一查詢、記憶,這裡將這些按鍵對映整理成列表供你檢視。根據快捷鍵型別分為以下 2 類快捷鍵型別,供你區別查詢:

  • 基礎快捷鍵:Vim 編輯器自帶的非常基礎的快捷鍵;
  • 非基礎快捷鍵:配置的、外掛自帶的、其它常用的快捷鍵。

基礎快捷鍵

提示:<leader>: 空格鍵。

Vim基礎快捷鍵

非基礎類快捷鍵

提示:<leader>:空格鍵。

Vim非基礎快捷鍵

參考

一些值得參考學習的文章:

  • Using Vim for Go Development
  • 一個很受歡迎的 vimrc 配置

歡迎關注我的公眾號【令飛程式設計】,會不定期分享 Go、雲原生、AI 相關的技術棧。

相關文章