サークルでGoサーバ書いて成長した話

こんにちは TechTrain Advent Calender 2019 12日目です．

# はじめに
 部活のプロジェクトでTechTrainというSNSアプリをGoで書きました．
 このプロジェクトでは技術好き学生向けのSNSアプリを開発しようということでモバイル班(Android，iOS)，サーバ班，デザイン班に別れてチーム開発を行いました．
 自分は編入組で4月後半に部活に入ったため途中からサーバ班に参加させていただきました．
自分が入った段階ではプロジェクトでどのようなものを作るか，サーバはGo言語を使用すると決まっていました．サーバ班全員Go言語メインで書いたことはなく勉強がてら触ってみようとなりメンターさんからもGoサインが出たので決定したらしいです．自分も昔少し触っただけでガッツリ書いたことがなく，新しい言語を触れるということでとても楽しみでした．新しい言語触るのって楽しいですよね．

プロジェクトの詳しい話に関しては他のプロジェクトメンバーの記事を見ると面白いと思います．
- [TechTrainを利用してチームでアプリ開発をした話（Android編）](https://qiita.com/switch23/items/30ee2a77cc25fdd2fabd)
- [開発初心者が8か月間のチーム開発に参加して感じた反省](https://qiita.com/NYuki12/items/f2544932a64190c5ee2f)
- TechTrain Advent Calender 2019 14日目
- TechTrain Advent Calender 2019 17日目
- TechTrain Advent Calender 2019 19日目
- TechTrain Advent Calender 2019 21日目

# 本編
 ところでみなんさんプログラミングをするのに必要なものって何だとおもいますか?
そう **テキストエディタ** ですよね．ちなみにこの記事もNeovimで下書きを書いています．
新しい言語を触るということであればテキストエディタの設定をするのはこの世の理です．
昔Go言語を少し触ったときは今ほどLSPが主流ではなかったため今回Go言語を書くにあたってVimの設定を見直しました．
私のVimの設定ファイルのディレクトリ構成はこうなっています．

``` shell
~/.config/nvim
├── after
│   └── ftplugin
│       ├── go.vim
│       ├── java.vim
│       ├── json.vim
│       ├── plaintex.vim
│       ├── prolog.vim
│       ├── python.vim
│       ├── rust.vim
│       └── tex.vim
├── autoload
│   └── aload.vim
├── dein.toml
├── dein_lazy.toml
├── ftdetect
│   └── pu.vim
├── init.vim
└── plugin
    ├── keymap.vim
    ├── lightline.vim
    └── syntastic.vim
```

では設定を一部抜粋し説明していきます．

まず起動時に読み込むプラグインです．

``` vim:dein.toml
[[plugins]]
repo = 'autozimu/LanguageClient-neovim'
rev = 'next'
build = 'bash install.sh'
hook_add = '''
  set hidden
  let g:LanguageClient_serverCommands = {
        \ 'cpp':  ['clangd'],
        \ 'rust': ['rustup', 'run', 'stable', 'rls'],
        \ 'go':   ['gopls']
        \}

  let g:LanguageClient_diagnosticsEnable = 0

  let g:LanguageCliet_autoStart = 1
  nnoremap <Space>lh :call LanguageClient#textDocument_hover()<CR>
  nnoremap <Space>ld :call LanguageClient#textDocument_definition()<CR>
  nnoremap <Space>lr :call LanguageClient#textDocument_rename()<CR>
'''

[[plugins]]
repo = 'vim-scripts/smartchr'
hook_add = '''
  inoremap <expr> = smartchr#loop(' = ',' == ', '=', '==')
  inoremap <expr> , smartchr#loop(', ',',')
'''

[[plugins]]
repo = 'w0rp/ale'
hook_add = '''
  setlocal signcolumn=yes
'''
```

今回の設定変更のメインとなるのがLSPの設定ですね．いままではdeoplete-goを使っていたのですが現在のエディタ界隈では補完はLSPに任せるのが主流になっているため私もLanguegeClient-neovimからGoのLSPであるgoplsを呼び出しています．

smartchrは特定のキー入力をしたときに別の入力を行うものです．例えば

``` vim
  inoremap <expr> , smartchr#loop(', ',',')
```

このように書くと`,`をキー入力したときに`, `が挿入されます．もう一度押すとリストの次の要素である`,`に変化します．
上に記述した`=`に関してのリストは汎用的に使っているものなので`ftplugin`でまた定義し直します．

aleはシンタックスチェックを行ってくれるもので記述に間違いがあれば警告してくれます．


次にdeinの遅延読み込みの機能を使っているプラグインです．

``` vim:after/dein_lazy.toml
[[plugins]]
repo = 'Shougo/deoplete.nvim'
on_event = 'insertCharPre'
hook_source = '''
  let g:deoplete#enable_at_startup = 1
  let g:deoplete#auto_complete_delay = 0
  let g:deoplete#augo_complete_start_length = 1
  let g:deoplete#enable_camel_case = 0
  let g:deoplete#enable_ignore_case = 0
  let g:deoplete#enable_refresh_always = 1
  let g:deoplete#smart_case = 1
  let g:deoplete#file#enable_buffer_path = 1
  let g:deoplete#max_list = 10000
  let g:deoplete#max_list=1000
  imap <expr><tab> neosnippet#expandable_or_jumpable() ?
         \ "\<Plug>(neosnippet_expand_or_jump)" : "\<tab>"
'''
on_i = 1

[[plugins]]
repo = 'fatih/vim-go'
hook_add = '''
  let g:go_fmt_command = "goimports"
  let g:go_def_mapping_enabled = 0
  let g:go_doc_keywordprg_enabled = 0
'''
on_ft = ['go']

[[plugins]]
repo = 'tyru/caw.vim'
on_path = '.*'
```

deopleteは補完フレームワークとして使っているものです．

vim-goはVimでGoを使うのであれば入れたいものですね．Vim編集中にビルドやクイックフィックスが行えたり自動importやフォーマット修正をしてくれます．

caw.vimはGo言語だけに使っているものではないですが現在のバッファのファイルタイプに応じたコメントアウト簡単にできるようになります．


最後にファイルタイプがGoだったときに読み込まれる設定です．

``` vim:after/ftplugin/go.vim
inoremap <expr> = smartchr#loop(' := ',' == ', ' != ', ' = ', '=', '==')
```

Go言語では`:=`を使う機会が多いため`=`の入力で` := `が挿入されるようにします．

# おわり
Vim使っていると新しい言語に触れた際に自分の設定ファイルの成長を感じられてとてもよいですね!
皆さん良きVimライフを!