I do ALL my coding over SSH from a windows machine, and most editors leave a lot to be desired in the way of code-completion, options, running, and debugging code. Here’s some things i’ve done that have made that loads easier for me, and hopefully for you too.

The documentation is spread out all over creation in many buried guithub pages, so here I’ll try and pull it all together and consumable.


  • Code completion in golang
  • Tab completion of variable names, package names, function names, etc…
  • go fmt and go lint on file save
  • automatic go file header creation when editing a new *.go file


Here we’ll set up GoLang auto-completion, automatic go fmt and go lint on file save, and some other helpful things. Vim8 works, but really here i use neovim because i’ve found the setup and operation to be FAR superior to mainline vim distributions.

Even through i use Arch Linux for my development box, i’ll assume other people will be using a Debian/Ubuntu system, so i’m re-abstracting all my commands for that.


  • I assume you’re using *NIX in some manner.
    • If you’re using windows, i cant guarantee this won’t make Bill Gates come punch you in the face.
  • Ability to install packages (if this isn’t your computer you better ask someone first. Go find an adult and ask for sudo permissions please).
  • python3, pip3 installed:
    • sudo apt install python3 python3-pip -y
  • pynvim package from pip3:
    • pip3 install (--user) pynvim (user is optional depending on if you want that package on the entire system, or just for your user.
  • Probably some beer or wine, depending on the time of day.


Phase 1: Installing NeoVim

  1. First we have to install neovim
    • sudo apt update
    • sudo apt install neovim
  2. Now decide how nvim gets launched:
    1. You learn to execute nvim instead of vi: (probably not)
      • nvim $FILE
    2. You want this to work only for you (probably):
      • echo "alias vi='nvim'" >> ~/.bashrc
      • source ~/.bashrc
    3. You want this to be a system wide change: (Maybe?)
      • echo "alias vi='nvim'" >> ~/etc/bashrc OR (DANGER!)
      • ln -s /sbin/nvim /sbin/vi
  3. You should now be able to run nvim from a shell (it works JUST like vi, but better and faster, and with easier advanced plugins)

Phase 2: Installing vim-plug

This one is easy! download vim-plug into your nvim autoload directory:

curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs \

Phase 3: Installing vim-go

  1. Edit your neovim init file vi ~/.config/nvim/init.vim and put in there the following:
    call plug#begin('~/.config/nvim/plugged')
    Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }
    call plug#end()


  2. launch nvim and once its open type :GoInstallBinaries and hit enter. It’ll download and install the rest of what it needs to on its own.
  3. Now you have the base framework setup, we can install all the goodies on top of that!

Phase 4: All the plugins and internal bits

  1. Now we’re going to install gocode which is a golang binaries that returns possible completion options, this is the engine that feeds the plugin beast.

    • From you CLI run go get -u github.com/nsf/gocode
    • This will fetch all the backend packages that you need to run.
  2. Once that completes, we’re going to add 3 things to ~/.config/nvim/init.vim:

    1. nsf/gocode - this binary we just talked about
    2. deoplete - A dark powered asynchronous completion framework for neovim/Vim8
    3. deoplete-go - a golang plugin for deoplete that will actually query gocode
    call plug#begin('~/.config/nvim/plugged`)
    Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }
    Plug 'nsf/gocode', { 'rtp': 'vim', 'do': '~/.vim/plugged/gocode/vim/symlink.sh' }
    Plug 'Shougo/deoplete.nvim', { 'do': 'UpdateRemotePlugins' }
    Plug 'deoplete-plugins/deoplete-go', { 'do': 'make' }
    call plug#end()


  3. Now, after the call plug#end() add the following:

    1. To speed things up: (prevent host checks ever startup)
      let g:python3_host_prog = '/sbin/python3'
      let g:python3_host_skip_check = 1
    2. To Enable gocode completion by default:
      let g:deoplete#enable_at_startup
    3. And to tell deoplete how to query gocode:
      let g:deoplete#sources#go#gocode_binary = $GOPATH.'bin/gocode'
      let g:deoplete#sources#go#sort_class = ['package', 'func', 'type', 'var', 'const']

    (Feel free to re-order those to your liking, it controls what gets suggested first)

  4. Now, if you want all that to work with tab completion (instead of the default CTRL+N) instruct neovim to remap TAB when the autocompletion window is open (i do this at the top of the file):
    inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"

A complete init.vim could look like this:

" <TAB>: completion
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"

" vim-plug stuff
call plug#begin('~/.config/nvim/plugged')
Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }
Plug 'nsf/gocode', { 'rtp': 'nvim', 'do': '~/.config/nvim/plugged/gocode/nvim/symlink.sh' }
Plug 'Shougo/deoplete.nvim', { 'do': 'UpdateRemotePlugins' }
Plug 'deoplete-plugins/deoplete-go', { 'do': 'make' }
call plug#end()
let g:python3_host_prog = '/sbin/python3'
let g:python3_host_skip_check = 1
let g:deoplete#enable_at_startup = 1
let g:deoplete#sources#go#gocode_binary = $GOPATH.'bin/gocode'
let g:deoplete#sources#go#sort_class = ['package', 'func', 'type', 'var', 'const']
  1. Once you save and close the file, run nvim again and then type the vim command: :PlugInstall to install the plugins into NeoVim.
  2. Since we’ve installed things, lets tell vim-go to update any binaries and dependencies using :GoUpdateBinaries
  3. After the process completes, you’ll want to update the deoplete plugins using :UpdateRemotePlugins (it may have complained about that already)

Everything should be working now, and you’re off and running! When you open a go file, vim-go+deoplete read the imported packages and add them as auto completion options. If you find completion isn’t working, try saving the file and re-opening it, sometimes that helps.