vimのGoサポートが手厚くて打ち震えている

# はじめに

タイトルの通りvimで作るGoの開発環境が便利なのでまとめたものです。
特にコードリーディングに便利な設定を紹介します。

# 参考

本稿を書くに当たって参考になった記事です。
日付が新しい順に並べていますので下の方は古い記述を含んでいます。

vim-go-extra を公開致します。
 http://vim-jp.org/blog/2014/09/02/vim-go-extra.html

Go 1.2.1 の環境構築 Homebrew + Vim 編 (2014.03)
 http://qiita.com/methane/items/4905f40e4772afec3e60

Big Sky :: Vimを使ったGo言語開発手法
 http://mattn.kaoriya.net/software/vim/20130531000559.htm

goのvimコマンド「Fmt」が、実はquickfixに登録してくれてて最高だった
 http://qiita.com/umisama/items/2e38139e0d3f4410446e

Go用のvim設定
 http://qiita.com/hnakamur/items/f39fde28bcfe4beaaaba

Vim for Golang :: Metal3d
 http://www.metal3d.org/ticket/2013/07/07/vim-for-golang

Goの開発環境(Vim + Vundle編)
 http://qiita.com/todogzm/items/3c281da10287f7383487

Go言語の初心者が見ると幸せになれる場所
 http://qiita.com/tenntenn/items/0e33a4959250d1a55045

mattyw: Using vim's path to speed up your Go project
 http://mattyjwilliams.blogspot.jp/2013/01/using-vims-path-to-speed-up-your-go.html

VimでGoのコードを書くときにやっておきたいこと
 http://qiita.com/methane/items/d82b9f28b97b5c3bd08a

VimFiler で NERDTree のような Explorer を快適に実現する方法 - sugoi < yabai < kimoi
 http://hrsh7th.hatenablog.com/entry/20120229/1330525683

# できるようになること

## VimFiler + Tagbar でIDEのような一覧性

VimFilerで後述する`:VimFilerTree`コマンドとTagBarプラグインで`:Tagbar`コマンドを実行したものです。
ツリー表示の定番はNERDTreeですが個人的な好みでVimFilerを使っています。
それぞれファイル名や関数名にカーソルを合わせて`Enter`を押すとジャンプします。

![VimFilerTree + Tagbar](https://qiita-image-store.s3.amazonaws.com/0/8995/bec12ce3-f0a4-7553-3068-0269f7cab1ce.png)
[画像だけを表示](https://qiita-image-store.s3.amazonaws.com/0/8995/bec12ce3-f0a4-7553-3068-0269f7cab1ce.png)

## 時にはUnite-outlineも使いたい

`:Unite outline`でアウトライン表示もできます。

![Unite-outline](https://qiita-image-store.s3.amazonaws.com/0/8995/534439ca-cec9-b59a-1c8b-82c2a244a1a8.png)
[画像だけを表示](https://qiita-image-store.s3.amazonaws.com/0/8995/534439ca-cec9-b59a-1c8b-82c2a244a1a8.png)

## gdで定義にジャンプ

下のウインドウの15行目の`NewAnsiColorWriter`にカーソルを合わせて`gd`を入力したものです。
画面分割されて上のウインドウにその定義があるファイルを開いています。

![Goto Declaration](https://qiita-image-store.s3.amazonaws.com/0/8995/f5b76472-950f-6dd6-a0be-4575e113b07b.png)
[画像だけを表示](https://qiita-image-store.s3.amazonaws.com/0/8995/f5b76472-950f-6dd6-a0be-4575e113b07b.png)

## :Godocでドキュメント表示

下のウインドウの17行目の`fmt.Println`にカーソルを合わせて`:Godoc`コマンドを実行したものです。
画面分割されて上のウインドウにGodocを開いています。

![Godoc](https://qiita-image-store.s3.amazonaws.com/0/8995/2832dc5d-28c9-ebb2-9602-1ede26d6d75d.png)
[画像だけを表示](https://qiita-image-store.s3.amazonaws.com/0/8995/2832dc5d-28c9-ebb2-9602-1ede26d6d75d.png)

# 環境構築

## 環境変数

### macでhomebrewの場合
```sh
export GOROOT=/usr/local/opt/go/libexec
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
```

### windowsの場合
```bat
GOROOT=C:\go
GOPATH=%USERPROFILE%\go
PATH=%GOPATH%\bin;%GOROOT%\bin;%PATH%
```

## ツール

`$GOPATH/bin`にコマンドがインストールされます。

```sh
go get -u golang.org/x/tools/cmd/goimports
go get -u golang.org/x/tools/cmd/godoc
go get -u golang.org/x/tools/cmd/vet
go get -u golang.org/x/tools/cmd/cover
go get -u github.com/nsf/gocode
go get -u github.com/golang/lint/golint
go get -u github.com/rogpeppe/godef
go get -u github.com/jstemmer/gotags
```

Windowsの場合は以下のようにWindowsアプリケーションでビルドすればvimからコマンド実行する時にウインドウが表示されなくなるのでお勧めです。

```sh
go get -u -ldflags -H=windowsgui golang.org/x/tools/cmd/goimports
go get -u -ldflags -H=windowsgui golang.org/x/tools/cmd/godoc
go get -u -ldflags -H=windowsgui golang.org/x/tools/cmd/vet
go get -u -ldflags -H=windowsgui golang.org/x/tools/cmd/cover
go get -u -ldflags -H=windowsgui github.com/nsf/gocode
go get -u -ldflags -H=windowsgui github.com/golang/lint/golint
go get -u -ldflags -H=windowsgui github.com/rogpeppe/godef
go get -u -ldflags -H=windowsgui github.com/jstemmer/gotags
```

## vimrc

各種vimプラグイン、Goの設定、VimFilerでツリー表示するための設定です。

```vim:~/.vimrc
" for Neobundle {{{
if has('win32')
    let s:vim_home=expand('~/vimfiles')
else
    let s:vim_home=expand('~/.vim')
endif
if has('vim_starting')
    let &runtimepath.=printf(',%s/bundle/neobundle.vim', s:vim_home)
endif

set nocompatible
call neobundle#begin(expand(s:vim_home.'/bundle/'))
NeoBundleFetch 'Shougo/neobundle.vim'
call neobundle#end()

NeoBundle 'majutsushi/tagbar'
NeoBundle 'Shougo/vimfiler'
NeoBundle 'Shougo/vimproc'
NeoBundle 'Shougo/unite.vim'
NeoBundle 'Shougo/unite-outline'
NeoBundle 'dgryski/vim-godef'
NeoBundle 'vim-jp/vim-go-extra'
" vim-ft-goは最新版のvimを使えない場合のみ
NeoBundle 'google/vim-ft-go'
set rtp^=$GOPATH/src/github.com/nsf/gocode/vim

filetype plugin indent on
syntax on
NeoBundleCheck
" }}}

" for golang {{{
set path+=$GOPATH/src/**
let g:gofmt_command = 'goimports'
au BufWritePre *.go Fmt
au BufNewFile,BufRead *.go set sw=4 noexpandtab ts=4 completeopt=menu,preview
au FileType go compiler go
" }}}

" VimFilerTree {{{
command! VimFilerTree call VimFilerTree(<f-args>)
function VimFilerTree(...)
    let l:h = expand(a:0 > 0 ? a:1 : '%:p:h')
    let l:path = isdirectory(l:h) ? l:h : ''
    exec ':VimFiler -buffer-name=explorer -split -simple -winwidth=45 -toggle -no-quit ' . l:path
    wincmd t
    setl winfixwidth
endfunction
autocmd! FileType vimfiler call g:my_vimfiler_settings()
function! g:my_vimfiler_settings()
    nmap     <buffer><expr><CR> vimfiler#smart_cursor_map("\<Plug>(vimfiler_expand_tree)", "\<Plug>(vimfiler_edit_file)")
    nnoremap <buffer>s          :call vimfiler#mappings#do_action('my_split')<CR>
    nnoremap <buffer>v          :call vimfiler#mappings#do_action('my_vsplit')<CR>
endfunction

let my_action = {'is_selectable' : 1}
function! my_action.func(candidates)
    wincmd p
    exec 'split '. a:candidates[0].action__path
endfunction
call unite#custom_action('file', 'my_split', my_action)

let my_action = {'is_selectable' : 1}
function! my_action.func(candidates)
    wincmd p
    exec 'vsplit '. a:candidates[0].action__path
endfunction
call unite#custom_action('file', 'my_vsplit', my_action)
" }}}
```

```vim:~/.vim/ftplugin/go.vim
" gotags {{{
let g:tagbar_type_go = {
    \ 'ctagstype' : 'go',
    \ 'kinds'     : [
        \ 'p:package',
        \ 'i:imports:1',
        \ 'c:constants',
        \ 'v:variables',
        \ 't:types',
        \ 'n:interfaces',
        \ 'w:fields',
        \ 'e:embedded',
        \ 'm:methods',
        \ 'r:constructor',
        \ 'f:functions'
    \ ],
    \ 'sro' : '.',
    \ 'kind2scope' : {
        \ 't' : 'ctype',
        \ 'n' : 'ntype'
    \ },
    \ 'scope2kind' : {
        \ 'ctype' : 't',
        \ 'ntype' : 'n'
    \ },
    \ 'ctagsbin'  : 'gotags',
    \ 'ctagsargs' : '-sort -silent'
\ }
" }}}
```